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

4 5
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 #1: No

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 }
原文地址:https://www.cnblogs.com/Y-E-T-I/p/7687595.html