图论算法----强连通
poj 2186 Popular Cows
分析:直接求一下强连通分量,对于同一个强连通分量里面的结点状态是相同的,要求有多少个人被其他所有的人都认可,只有可能是拓扑排序的最后一个强连通的结点个数,判断一下其他节点是否都可以到该联通分量就ok了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #include <algorithm> 6 #include <map> 7 #include<vector> 8 #define maxn 10010 9 #define maxm 50010 10 using namespace std; 11 int n,m; 12 vector<int>G[maxn]; 13 vector<int>rG[maxn]; 14 vector<int>vs; 15 bool used[maxn]; 16 int cmp[maxn]; 17 void addedge(int u,int v){ 18 G[u].push_back(v); 19 rG[v].push_back(u); 20 } 21 void init(){ 22 for(int i=0;i<=n;++i){ 23 G[i].clear(); 24 rG[i].clear(); 25 } 26 } 27 void dfs(int u){ 28 used[u]=true; 29 for(int i=0;i<G[u].size();++i){ 30 if(!used[G[u][i]])dfs(G[u][i]); 31 } 32 vs.push_back(u); 33 } 34 void rdfs(int u,int k){ 35 used[u]=true; 36 cmp[u]=k; 37 for(int i=0;i<rG[u].size();++i){ 38 if(!used[rG[u][i]])rdfs(rG[u][i],k); 39 } 40 } 41 int scc(){ 42 memset(used,0,sizeof(used)); 43 vs.clear(); 44 for(int i=0;i<n;++i){ 45 if(!used[i])dfs(i); 46 } 47 memset(used,0,sizeof(used)); 48 int k =0; 49 for (int i=vs.size()-1;i>=0;--i){ 50 if(!used[vs[i]])rdfs(vs[i],k++); 51 } 52 return k; 53 } 54 void solve(){ 55 int nn = scc(); 56 int cnt =0,u=0; 57 for(int i=0;i<n;++i){ 58 if(cmp[i]==nn-1){ 59 u = i; 60 cnt++; 61 } 62 } 63 memset(used,0,sizeof(used)); 64 rdfs(u,0); 65 for(int i=0;i<n;++i){ 66 if(!used[i]){ 67 cnt=0; 68 break; 69 } 70 } 71 printf("%d\n",cnt); 72 } 73 int main (){ 74 while(scanf("%d%d",&n,&m)!=EOF){ 75 init(); 76 int x,y; 77 for(int i=0;i<m;++i){ 78 scanf("%d%d",&x,&y); 79 addedge(x-1,y-1); 80 } 81 solve(); 82 } 83 }
poj3683 Priest John's Busiest Day
题目意思:有n个事务,每个有两种时间段选择,问你可不可以安排使得n个事务不冲突。
分析:转成2-SAT求解,对于每一个事务,有两种选择就是是或者否,根据相应的条件完成建图后使用强连通求解2-SAT
把第i个事务拆成两个点i i+m分别对应开始时间段与结束时间段,然后根据时间段是否有冲突写出合取范式建图求解
对于规则a∨b 可以改写为 ┐a->b∧┐b->a 可以翻一下离散的书
si与sj冲突那么就可以写成 ┐xi V ┐xj 转为xi->┐xj 建边(i,j+m)
同理另外三种情况看代码
利用强连通求解2-SAT只需要判断i结点与i+m结点是不是在一个强连通分支里面,如果在说明两者同时成立,这显然是不合理的。
如果i结点的拓扑序在i+m前面则i成立即第i个事务选择在开始时执行否则在结束时执行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #include <algorithm> 6 #include <map> 7 #include<vector> 8 #define maxn 4010 9 #define maxm 50010 10 using namespace std; 11 int n,m; 12 vector<int>G[maxn]; 13 vector<int>rG[maxn]; 14 vector<int>vs; 15 bool used[maxn]; 16 int cmp[maxn]; 17 void addedge(int u,int v){ 18 G[u].push_back(v); 19 rG[v].push_back(u); 20 } 21 void init(){ 22 for(int i=0;i<=n;++i){ 23 G[i].clear(); 24 rG[i].clear(); 25 } 26 } 27 void dfs(int u){ 28 used[u]=true; 29 for(int i=0;i<G[u].size();++i){ 30 if(!used[G[u][i]])dfs(G[u][i]); 31 } 32 vs.push_back(u); 33 } 34 void rdfs(int u,int k){ 35 used[u]=true; 36 cmp[u]=k; 37 for(int i=0;i<rG[u].size();++i){ 38 if(!used[rG[u][i]])rdfs(rG[u][i],k); 39 } 40 } 41 int scc(){ 42 memset(used,0,sizeof(used)); 43 vs.clear(); 44 for(int i=0;i<n;++i){ 45 if(!used[i])dfs(i); 46 } 47 memset(used,0,sizeof(used)); 48 int k =0; 49 for (int i=vs.size()-1;i>=0;--i){ 50 if(!used[vs[i]])rdfs(vs[i],k++); 51 } 52 return k; 53 } 54 int s[maxn],t[maxn],d[maxn]; 55 void build(){ 56 for(int i=0;i<m;++i){ 57 for(int j=0;j<i;++j){ 58 if(min(s[i]+d[i],s[j]+d[j])>max(s[i],s[j])){ 59 //开始与开始冲突 xi->^xj&&xj->^xi 60 addedge(i,j+m); 61 addedge(j,i+m); 62 } 63 if(min(s[i]+d[i],t[j])>max(s[i],t[j]-d[j])){ 64 //开始与结束冲突 xi->xj&&^xj->^xi 65 addedge(i,j); 66 addedge(j+m,i+m); 67 } 68 if(min(t[i],s[j]+d[j])>max(t[i]-d[i],s[j])){ 69 //结束与开始冲突 ^xi->^xj&&xj->xi 70 addedge(i+m,j+m); 71 addedge(j,i); 72 } 73 if(min(t[i],t[j])>max(t[i]-d[i],t[j]-d[j])){ 74 //结束与结束冲突 ^xi->xj&&^xj->xi 75 addedge(i+m,j); 76 addedge(j+m,i); 77 } 78 } 79 } 80 } 81 void solve(){ 82 build(); 83 int k =scc(); 84 for(int i=0;i<m;++i){ 85 if(cmp[i]==cmp[m+i]){ 86 printf("NO\n"); 87 return ; 88 } 89 } 90 printf("YES\n"); 91 for(int i=0;i<m;++i){ 92 if(cmp[i]>cmp[i+m]){ 93 printf("%02d:%02d %02d:%02d\n",s[i]/60,s[i]%60,(s[i]+d[i])/60,(s[i]+d[i])%60); 94 } 95 else printf("%02d:%02d %02d:%02d\n",(t[i]-d[i])/60,(t[i]-d[i])%60,t[i]/60,t[i]%60); 96 } 97 } 98 int main (){ 99 while(scanf("%d",&m)!=EOF){ 100 init(); 101 n = 2*m; 102 int sh,sm,th,tm; 103 for(int i=0;i<m;++i){ 104 scanf("%d:%d %d:%d %d",&sh,&sm,&th,&tm,&d[i]); 105 s[i]=sh*60+sm; 106 t[i]=th*60+tm; 107 } 108 solve(); 109 } 110 }