标签:dfs 16px rip table else read sap mic air
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 8688 | Accepted: 3371 |
Description
Input
Output
Sample Input
3 6
0 3
1 2
4 5
0 1
0 2
4 1
4 2
3 5
2 2
0 0
Sample Output
4
题意
现在有N对钥匙(一共2N把,编号从0到2N-1),每对钥匙只能选其中一把。另有M扇门,每扇门能够被两把钥匙a,b中的任意一把打开,问能开的最大门数是多少(开门为递增顺序)
思路
2-SAT,找到矛盾关系。①如果a,b出现在同一对钥匙里,只能拿a或拿b。②如果c,d能打开同一扇门,为了最大化开门数,我们假定,不用c开门或不用d开门。
蕴含式表示形式:a->!b和b->!a,!c->d和!d->c。按照这个建图,求scc,如果i和i+2*n在一个强连通分量里(即i和!i在同一个主合取范式里)则无解。
由于求的是最大值,所以二分处理。
1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <queue> 6 #include <map> 7 8 using namespace std; 9 10 typedef pair<int,int> P; 11 12 const int maxn=6000; 13 14 vector<int> G[maxn]; 15 vector<int> rG[maxn]; 16 vector<int> vs; 17 18 int n,m; 19 20 bool used[maxn]; 21 int cmp[maxn]; 22 23 inline int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} 26 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 27 return x*f; 28 } 29 30 void init(){ 31 for(int i=0;i<maxn;i++){ 32 G[i].clear(); 33 rG[i].clear(); 34 cmp[i]=0; 35 } 36 } 37 38 void add_edge(int s,int t){ 39 G[s].push_back(t); 40 rG[t].push_back(s); 41 } 42 43 void dfs(int s){ 44 used[s]=true; 45 for(int i=0;i<G[s].size();i++){ 46 if(!used[G[s][i]]) dfs(G[s][i]); 47 } 48 vs.push_back(s); 49 } 50 51 void rdfs(int s,int k){ 52 used[s]=true; 53 cmp[s]=k; 54 for(int i=0;i<rG[s].size();i++){ 55 if(!used[rG[s][i]]) rdfs(rG[s][i],k); 56 } 57 } 58 59 int scc(){ 60 vs.clear(); 61 memset(used,0,sizeof(used)); 62 for(int i=0;i<4*n;i++){ 63 if(!used[i]) dfs(i); 64 } 65 memset(used,0,sizeof(used)); 66 int k=0; 67 for(int i=vs.size()-1;i>=0;i--){ 68 if(!used[vs[i]]) rdfs(vs[i],++k); 69 } 70 return k; 71 } 72 73 P key[maxn]; 74 P door[maxn]; 75 76 bool solve(int num){ 77 init(); 78 for(int i=0;i<n;i++){ 79 add_edge(key[i].first,key[i].second+2*n); 80 add_edge(key[i].second,key[i].first+2*n); 81 } 82 for(int i=0;i<num;i++){ 83 add_edge(door[i].first+2*n,door[i].second); 84 add_edge(door[i].second+2*n,door[i].first); 85 } 86 int k=scc(); 87 for(int i=0;i<2*n;i++){ 88 if(cmp[i]==cmp[i+2*n]){ 89 return false; 90 } 91 } 92 return true; 93 } 94 95 int main(){ 96 while(true){ 97 n=read();m=read(); 98 if(n==0&&m==0) break; 99 for(int i=0;i<n;i++){ 100 key[i].first=read(); 101 key[i].second=read(); 102 } 103 for(int i=0;i<m;i++){ 104 door[i].first=read(); 105 door[i].second=read(); 106 } 107 int l=0,r=m; 108 int ans=0; 109 while(l<=r){ 110 int mid=(l+r)/2; 111 if(solve(mid)){ 112 ans=max(ans,mid); 113 l=mid+1; 114 } 115 else r=mid-1; 116 } 117 printf("%d\n",ans); 118 } 119 return 0; 120 }
标签:dfs 16px rip table else read sap mic air
原文地址:http://www.cnblogs.com/hymscott/p/6534394.html