bzoj3332: 旧试题
这题就是最大生成树。
把两个点之间的期望建边排序。
把相同的期望一起做,那么在这个做之前,这些有着相同期望的点两两肯定不连,否则就输出No了。
相同的做完之后,再次for一遍check一下有没有两两之间还是不能连的,有那么输出No。
其他的就是直接并查集。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int n,m; bool mp[1100][1100]; struct node { int x,y,d; }a[2100000];int len; void ins(int x,int y,int d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; } bool cmp(node n1,node n2) { if(n1.d>n2.d)return true; return false; } void init() { scanf("%d%d",&n,&m); int x,y; memset(mp,false,sizeof(mp)); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); mp[x][y]=true;mp[y][x]=true; } len=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&x); if(i<j) ins(i,j,x); } sort(a+1,a+len+1,cmp); } //-------------init--------------- int fa[1100]; int findfa(int x) { if(fa[x]==x)return x; fa[x]=findfa(fa[x]);return fa[x]; } int top,stax[1100000],stay[1100000]; int main() { int T; scanf("%d",&T); for(int tt=1;tt<=T;tt++) { init(); for(int i=1;i<=n;i++)fa[i]=i; bool bk=true;top=0;int last=0; for(int i=1;i<=len;i++) { if(last!=a[i].d) { last=a[i].d; for(int j=1;j<=top;j++) if(findfa(stax[j])!=findfa(stay[j])) {bk=false;break;} top=0; if(bk==false)break; for(int j=i;a[j].d==a[i].d&&j<=len;j++) if(findfa(a[j].x)==findfa(a[j].y)) {bk=false;break;} if(bk==false)break; if(a[i].d==-1)break; } int x=a[i].x,y=a[i].y; int fx=findfa(x),fy=findfa(y); if(fx!=fy) { if(mp[x][y]==true)fa[fx]=fy; else { top++; stax[top]=a[i].x; stay[top]=a[i].y; } } } if(bk==true)printf("Case #%d: Yes\n",tt); else printf("Case #%d: No\n",tt); } return 0; }
pain and happy in the cruel world.