1 条题解

  • 0
    @ 2025-8-24 23:15:30

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar gdf_yhm
    智者搭桥,愚者筑墙。

    搬运于2025-08-24 23:15:30,当前版本为作者最后更新于2025-07-14 22:31:35,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    P12427

    思路

    对原来的边建点。若 ii 边能接到 jj 边,连边 iji\to jm2m^2 条边,O(m2)O(m^2) dfs 找环。需要减少边数。

    对原来的点建虚点。连边 iyii\to y_ixiix_i\to i,但是有颜色要求,不能直接在虚点中转。

    对于 cicjc_i\neq c_j,一定有一个二进制位不同,在每个二进制位上中转。建虚点 id(i,j,0/1)id(i,j,0/1) 代表原图的 ii 点,第 jj0/10/1。若 cic_i 二进制第 jj 位为 00,连边 iid(yi,j,1)i\to id(y_i,j,1)id(xi,j,0),iid(x_i,j,0),im+40nm+40n 个点,40m40m 条边,复杂度 O(nlogn)O(n\log n)

    然后卡常就完了。

    code

    int n,m;
    int head[maxn*41],tot;
    struct nd{
        int nxt,to;
    }e[maxn*40];
    void add(int u,int v){e[++tot]={head[u],v};head[u]=tot;}
    int ans[maxn],num;
    bool vis[maxn*41],bk[maxn*41];
    int st[maxn*41],tp;
    // void dfs(int u){
        // vis[u]=bk[u]=1;st[++tp]=u;
        // for(int i=head[u];i;i=e[i].nxt){
            // int v=e[i].to;
            // if(!vis[v])dfs(v);
            // else if(bk[v]){
                // if(num)continue;
                // for(int i=tp;i;i--){    
                    // if(st[i]<=m)ans[++num]=st[i];
                    // if(st[i]==v)break;
                // }
            // }
            // if(num)break;
        // }
        // bk[u]=0;tp--;
    // }
    void work(){
        n=read();m=read();
        for(int i=1;i<=m+40*n;i++)head[i]=vis[i]=0;tot=0;
        for(int i=1;i<=m;i++){
            int x=read(),y=read(),c=read();
            for(int j=0;j<20;j++){
                int v=(c>>j)&1;
                add(((v^1)*20+j)*n+x+m,i);
                add(i,(v*20+j)*n+y+m);
            }
        }
        num=0;for(int i=1;i<=m+40*n;i++)if(!vis[i]){
        	vis[i]=bk[i]=1,st[++tp]=i;
        	while(tp){
        		int u=st[tp];
    		    for(int &i=head[u];i;i=e[i].nxt){
    		        int v=e[i].to;
    		        if(!vis[v]){vis[v]=bk[v]=1,st[++tp]=v;break;}
    		        else if(bk[v]&&!num){
    		            for(int i=tp;i;i--){    
    		                if(st[i]<=m)ans[++num]=st[i];
    		                if(st[i]==v)break;
    		            }
    		        }
    		    }
        		if(!head[u])bk[u]=0,tp--;
        	}
        	if(num)break;
        }
        if(!num){puts("NO");return ;}
        puts("YES");write(num),putchar(' ');for(int i=num;i;i--)write(ans[i]),putchar(' ');puts("");
    }
    
    • 1

    信息

    ID
    12226
    时间
    4000ms
    内存
    1024MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者