bzoj 3332 旧试题
Description
圣诞节将至。一年一度的难题又摆在wyx面前——如何给妹纸送礼物。
wyx的后宫有n人,这n人之间有着复杂的关系网,相互认识的人有m对。wyx想要量化后宫之间的亲密度,于是准备给每对认识关系估一个亲密度。亲密度是
个正整数,值越大说明越亲密。当然有可能有些后宫之间不直接认识,为此wyx定义了一个值f(i,j),代表从第i个后宫开始不断经过认识的人到j,经过
的亲密度最小的一对关系的最大值。不过也有可能有些后宫的朋友圈互相独立,怎么也没法通过认识的人互相到达,那么f(i,j)就为-1。
举个例子,wyx的后宫有4人,编号为1~4。后宫1和2之间的亲密度为3,后宫2和3之间的亲密度为4,后宫1和3之间的亲密度为2,后宫4由于不明原
因被孤立了。那么f(1,2)=f(1,3)=3,f(2,3)=4,f(1,4)=f(2,4)=f(3,4)=-1。
wyx认为了解后宫之间的亲密程度对于他选择礼物有着很重大的意义,于是他找了几个路人,测出了所有后宫之间的f(i,j)值。不过wyx怀疑路人在坑
爹,他想知道,是否能找到一组后宫之间的亲密度方案满足路人测出的f(i,j)值?由于他还要去把妹,这个问题就交给你了。
Input
第一行一个正整数T,代表数据组数。
接下来T组数据,每组数据第一行两个正整数n、m,代表点数和边数。
接下来m行,每行两个正整数代表一条边。
接下来n行每行n个整数,代表所有的f(i,j)值。
Output
对于每组数据,输出 "Yes" 或者 "No"。(详细参看样例输出)
Sample Input
3
1 2
1 3
1 4
2 3
2 4
0 5 5 5
5 0 5 5
5 5 0 4
5 5 4 0
4 4
1 2
1 3
2 3
2 4
0 4 4 4
4 0 4 5
4 4 0 4
4 5 4 0
4 2
1 2
2 3
0 3 3 -1
3 0 4 -1
3 4 0 -1
-1 -1 -1 0
Sample Output
Case #2: Yes
Case #3: Yes
HINT
数据范围
T ≤ 30
n ≤ 1000
m ≤ 300000
f(i,j)=-1 或者 1 ≤ f(i,j) ≤ 32767
注意输入量奇大无比!
首先只有存在的路有可能有值,然后在存储矩阵的同时对于本来就有边的情况
直接存下来这条边的值,然后跑一次最大生成树,在最大生成树的同时就可以求出矩
阵的信息。
正确性证明:首先,对于有边相连的点,其边的权值由信息定义可知显然不会更大,
然后如果真实值比赋的值要小,那么也不会对最大生成树有影响(因为那样就说明这
两个点间有一条路所经过的所有边权值都比赋给它们的边的值要大,由最大生成树的
定义可知这两点之间的边一定不会被选上,
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct XXX 7 { 8 int u,v; 9 } Link[300001]; 10 struct Node 11 { 12 int next,to,dis; 13 } edge[600001]; 14 int f[1001][1001],n,m,set[10001]; 15 int vis[1001]; 16 int gi() 17 { 18 int x=0,flag=1; 19 char ch=getchar(); 20 while (ch<'0'||ch>'9') 21 { 22 if (ch=='-') flag=-1; 23 ch=getchar(); 24 } 25 while (ch>='0'&&ch<='9') 26 { 27 x=x*10+ch-'0'; 28 ch=getchar(); 29 } 30 return x*flag; 31 } 32 int find(int x) 33 { 34 if (set[x]!=x) set[x]=find(set[x]); 35 return set[x]; 36 } 37 bool cmp(XXX a,XXX b) 38 { 39 return (f[a.u][a.v]>f[b.u][b.v]); 40 } 41 int head[1001],num; 42 void add(int u,int v,int dis) 43 { 44 num++; 45 edge[num].next=head[u]; 46 head[u]=num; 47 edge[num].to=v; 48 edge[num].dis=dis; 49 } 50 void dfs(int x,int s) 51 { 52 int i,t; 53 vis[x]=s; 54 for (i=head[x]; i; i=edge[i].next) 55 { 56 int v=edge[i].to; 57 if (vis[v]==-1) 58 { 59 dfs(v,min(s,edge[i].dis)); 60 } 61 } 62 } 63 bool pd(int x,int y) 64 { 65 if (x==y&&f[x][y]) return 0; 66 if (x==y&&f[x][y]==0) return 1; 67 if (f[x][y]!=f[y][x]) return 0; 68 if (vis[y]!=f[x][y]) return 0; 69 return 1; 70 } 71 int main() 72 { 73 int T,TT,i,j,cnt,flag; 74 freopen("problem.in","r",stdin); 75 freopen("problem.out","w",stdout); 76 cin>>T; 77 TT=0; 78 while ((++TT)<=T) 79 { 80 cin>>n>>m; 81 num=0; 82 memset(head,0,sizeof(head)); 83 cnt=1; 84 for (i=1; i<=m;cnt++,i++) 85 { 86 Link[i].u=gi();Link[i].v=gi(); 87 } 88 for (i=1; i<=n; i++) 89 { 90 for (j=1; j<=n; j++) 91 f[i][j]=gi(); 92 } 93 sort(Link+1,Link+m+1,cmp); 94 cnt=0; 95 for (i=1; i<=n; i++) set[i]=i; 96 for (i=1; i<=m; i++) 97 { 98 int p=find(Link[i].u); 99 int q=find(Link[i].v); 100 if (p!=q) 101 { 102 ++cnt; 103 add(Link[i].u,Link[i].v,f[Link[i].u][Link[i].v]); 104 add(Link[i].v,Link[i].u,f[Link[i].u][Link[i].v]); 105 set[p]=q; 106 if (cnt==n-1) break; 107 } 108 } 109 flag=0; 110 for (i=1; i<=n; i++) 111 { 112 if (flag) break; 113 memset(vis,-1,sizeof(vis)); 114 dfs(i,2e9); 115 for (j=1; j<=i; j++) 116 { 117 if (pd(i,j)==0) 118 { 119 flag=1; 120 break; 121 } 122 } 123 } 124 if (flag) cout<<"Case #"<<TT<<": No"<<endl; 125 else cout<<"Case #"<<TT<<": Yes"<<endl; 126 } 127 }