题目链接
题目描述:
图片说明

思路分析:
DP[i][j]表示将初始位置为K的电脑进行第i次操作后当前位置为j的最小不执行命令次数。
这题的DP方程是真的巧妙,因为我们考虑的是初始位置为K的电脑最终放在j位置的最小不执行次数,所以每一个交换命令意味着,1、这一层交换不执行,坏电脑在X位置的最小并不执行次数就是就在上一层状态x不执行次数加一,2、执行就是坏电脑在Y的位置移到了X位置,所以坏电脑在X位置的最小不执行次数就等于上一层坏电脑在Y位置的最小不移动次数(第一次见这样的状态转移方式记录一下)。因为每一层只交换命令的x,y,其他位置不变所以时间复杂度为O(m).

题目代码:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int t;
int n,m,k;
struct ty{
    int x;
    int y;
};
ty a[100005];
int f[2][100005];
int main(){
    scanf(" %d",&t);
    while(t--){
        scanf(" %d %d %d",&n,&m,&k);
        for(int i=1;i<=m;i++) scanf(" %d %d",&a[i].x,&a[i].y);
        for(int i=0;i<=1;i++){
            for(int j=0;j<=100001;j++) f[i][j]=INF;
        }
        f[0][k]=0;
        f[1][k]=0;
        for(int i=1;i<=m;i++){
            //for(int j=1;j<=n;j++) f[i&1][j]=f[(i-1)&1][j];
            int x=a[i].x,y=a[i].y;
            /*1、这一层交换不执行,坏电脑在X位置的最小并不执行次数就是就在上一层状态x不执行次数加一
            2、执行就是坏电脑在Y的位置移到了X位置,
            所以坏电脑在X位置的最小不执行次数就等于上一层坏电脑在Y位置的最小不移动次数 */
            f[i&1][x]=min(f[(i-1)&1][y],f[(i-1)&1][x]+1);
            f[i&1][y]=min(f[(i-1)&1][x],f[(i-1)&1][y]+1);
            f[(i+1)&1][x]=f[i&1][x];
            f[(i+1)&1][y]=f[i&1][y];
            //for(int j=1;j<=n;j++) cout<<f[i&1][j]<<" ";
            //cout<<"\n";
        }
        for(int i=1;i<=n;i++){
            if(i!=n){
                if(f[m&1][i]!=INF) printf("%d ",f[m&1][i]);
                else printf("-1 ");
            }
            else{
                if(f[m&1][i]!=INF) printf("%d",f[m&1][i]);
                else printf("-1");
            }
        }
        cout<<"\n";
    }
    return 0;
}