zoukankan      html  css  js  c++  java
  • GMOJ 5275. 水管 题解

    也许是吧

    首先

    明显的,不论是prim还是kruskal,都是可以生成所有最小生成树的,只要精心构造一下输入边的顺序即可。

    所以,我们可以精心构造边的顺序使得两次生成的最小生成树不一样,这就可以作为最小生成树不唯一的充分条件。 (充分必要条件?也许是吧,能A就行)

    于是

    众所周知,在kruskal中,可以作为最小生成树边但没有被选上的边纯粹是运气不好,被心情不好的sort排到了后面。

    那么,我们可以用一种巧妙的办法,使得两次kruskal中相同权值的边翻转一下,这样一条可能的边一定会去到占用它位置的边的前面。

    为了区分任意两条边,我们给每一条边打一个唯一的时间戳,在排序时以第二关键字参与排序。一次顺序,一次倒序,这样就可以使得相同权值的边的顺序反转。然后再做一遍最小生成树,如果不一样,那么说明最小生成树不唯一。

    当然,也可以手动处理出每个权值的范围,直接翻转,会跑得快一些。

    那么

    上代码。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct arc{
    	int x,y,z,key;
    	bool used;
    }a[200010];
    int t,n,m,s[100010];
    bool comp1(arc a,arc b){
    	return(a.z<b.z||(a.z==b.z&&a.key<b.key));
    }
    bool comp2(arc a,arc b){
    	return(a.z<b.z||(a.z==b.z&&a.key>b.key));
    }
    template<typename T>void read(T &x){
    	char c=getchar();
    	for(;c<33;c=getchar());
    	for(x=0;(47<c)&&(c<58);x=x*10+c-48,c=getchar());
    }
    int root(int m){
    	if(s[m]){
    		return(s[m]=root(s[m]));
    	}
    	return(m);
    }
    void uni(int x,int y){
    	s[root(y)]=root(x);
    }
    int main(){
    	for(read(t);t;t--){
    		read(n);read(m);
    		for(int i=1;i<=m;i++){
    			read(a[i].x);read(a[i].y);read(a[i].z);
    			a[i].used=0;
    			a[i].key=i;
    		}
    		sort(a+1,a+m+1,comp1);
    		memset(s,0,sizeof(s));
    		long long ans=0,v=0;
    		for(int i=1,j=0;i<n;i++){
    			for(j++;j<=m&&root(a[j].x)==root(a[j].y);j++);
    			uni(a[j].x,a[j].y);
    			ans+=a[j].z;
    			a[j].used=1;
    		}
    		sort(a+1,a+m+1,comp2);
    		memset(s,0,sizeof(s));
    		for(int i=1,j=0;i<n;i++){
    			for(j++;j<=m&&root(a[j].x)==root(a[j].y);j++);
    			uni(a[j].x,a[j].y);
    			if(!a[j].used){
    				v=1;
    				break;
    			}
    		}
    		printf("%lld
    ",ans);
    		printf(v?"No
    ":"Yes
    ");
    	}
    }
    

    2020/8/4 update:

    显然这个东西的正确性是有问题的

    ????/?/? update:

    显然按照是否被用过来排序就对了

  • 相关阅读:
    Poj 3177 Redundant Paths (双连通分支+节点统计)
    Uva 796 Critical Links (割边+排序)
    Lightoj 1020
    Flip Game---poj1753(状压+bfs)
    Best Cow Line---poj3617(贪心)
    滑雪---poj1088(动态规划+记忆化搜索)
    King's Quest---poj1904(连通图缩点)
    Steady Cow Assignment---poj3189(多重匹配+二分)
    B. Berland National Library---cf567B(set|模拟)
    HDU Today---hdu2112(最短路-_-坑在是无向图)
  • 原文地址:https://www.cnblogs.com/groundwater/p/13330578.html
Copyright © 2011-2022 走看看