codeforces 1131D-Gourmet choice
传送门:QAQQAQ
题意:有两个数组,一个数组有n个数,另一个数组有m个数。s[i][j]表示第一个数组第i个数和第二个数组第j个数的大小关系,要求构造出一种方案,使条件成立。
先考虑没有等于号的情况,那么就是裸的拓扑排序,现在多了一个等于号,就先进行并查集再拓扑就行了。
•注意点:1.在进行拓扑排序时一定要全部用father[x]作为节点
2.一定要全部并查集做完以后再连边,否则可能刚连完father[x]就变了
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=20001; 4 typedef pair<int,int> pii; 5 6 int p[N],a[N]; 7 int n,m,judge=0; 8 int t[N],ans[N],b[N]; 9 char s[1020][1020]; 10 vector <int> v[2080]; 11 12 int f(int x) 13 { 14 if(p[x]==x) return x; 15 return p[x]=f(p[x]); 16 } 17 18 void unite(int x,int y) 19 { 20 int xx=f(x),yy=f(y); 21 p[yy]=p[xx]; 22 } 23 24 int main() 25 { 26 memset(b,0,sizeof(b)); 27 memset(t,0,sizeof(t)); 28 scanf("%d %d",&n,&m); 29 for(int i=1;i<=n+m;i++) p[i]=i; 30 for(int i=1;i<=n;i++) 31 { 32 scanf("%s",s[i]+1); 33 for(int j=1;j<=m;j++) 34 { 35 if(s[i][j]=='=') 36 { 37 unite(i,j+n); 38 } 39 } 40 } 41 for(int i=1;i<=n;i++) 42 { 43 for(int j=1;j<=m;j++) 44 { 45 if(s[i][j]=='>') v[f(j+n)].push_back(f(i)),t[f(i)]++; 46 else if(s[i][j]=='<') v[f(i)].push_back(f(j+n)),t[f(j+n)]++; 47 } 48 } 49 priority_queue<pii> q; 50 for(int i=1;i<=n+m;i++) if(f(i)==i) judge++; 51 for(int i=1;i<=n+m;i++) 52 { 53 if(!t[p[i]]&&!b[p[i]]) 54 { 55 q.push(make_pair(p[i],1)); 56 b[p[i]]=1; 57 } 58 } 59 int sum=0,num=1; 60 while(!q.empty()) 61 { 62 int now=q.top().first,w=q.top().second; 63 q.pop(); sum++; 64 ans[now]=w; 65 for(int i=0;i<v[now].size();i++) 66 { 67 int pos=v[now][i]; 68 t[pos]--; 69 if(!t[pos]) 70 { 71 q.push(make_pair(pos,w+1)); 72 } 73 } 74 } 75 if(sum<judge) 76 { 77 puts("No"); 78 return 0; 79 } 80 puts("Yes"); 81 for(int i=1;i<=n;i++) printf("%d ",ans[p[i]]); puts(""); 82 for(int i=n+1;i<=m+n;i++) printf("%d ",ans[p[i]]); puts(""); 83 return 0; 84 }