2-st学习笔记

2-ST是一种巧妙的建图模式。。。。其实,主要是将互相限制的条件转化为有向图。实现时,将每个点拆成两点,对应这个点的两种取值,然后求强连通分量。由于每个点只能有一种取值,所以若强连通分量中某一个点拆成的两个点在同一个强连通分量中则问题无解。那么,如果问题有解,怎么得到问题的解呢?首先是根据计算出的强连通分量重新构图,构图时逆向构图,然后在新图上拓扑排序就能得到一组解。。。

  1 struct node
  2 {
  3     int v,next;
  4 };
  5 
  6 
  7 //每个点u拆成2*u和2*u+1
  8 //若有解,一组解存在ans中[0,n-1]
  9 const int MAX=1005;
 10 node edges[10005];
 11 int head[MAX],dfn[MAX],low[MAX],visit[MAX],color[MAX];
 12 int in[MAX],col[MAX],map[MAX][MAX],conflict[MAX];
 13 int n,m,e,index,cnt;
 14 stack<int> S;
 15 int ans[MAX];
 16 
 17 
 18 void Add(int u,int v)
 19 {
 20     edges[e].v=v;
 21     edges[e].next=head[u];
 22     head[u]=e++;
 23 }
 24 
 25 
 26 
 27 void Tarjan(int u)
 28 {
 29     int i,v;
 30 
 31     low[u]=dfn[u]=++index;S.push(u);visit[u]=1;
 32     for(i=head[u];i!=-1;i=edges[i].next)
 33     {
 34         v=edges[i].v;
 35         if(!dfn[v])
 36         {
 37             Tarjan(v);
 38             low[u]=min(low[u],low[v]);
 39         }
 40         else if(visit[v]) low[u]=min(low[u],dfn[v]);
 41     }
 42     if(dfn[u]==low[u])
 43     {
 44         cnt++;
 45         do
 46         {
 47             v=S.top();
 48             S.pop();
 49             visit[v]=0;
 50             color[v]=cnt;
 51         }while(u!=v);
 52     }
 53 }
 54 
 55 void Build()
 56 {
 57     int i,u,v;
 58 
 59     memset(map,0,sizeof(map));
 60     memset(in,0,sizeof(in));
 61     for(u=0;u<2*n;u++) for(i=head[u];i!=-1;i=edges[i].next)
 62     {
 63         v=edges[i].v;
 64 
 65         //逆向拓扑
 66         if(color[u]!=color[v]) map[color[v]][color[u]]=1;
 67     }
 68     for(u=1;u<=cnt;u++) for(v=1;v<=cnt;v++) if(map[u][v])
 69         in[v]++;
 70 }
 71 
 72 
 73 void Topsort()
 74 {
 75     int i,u,v;
 76 
 77     memset(col,0,sizeof(col));
 78     while(!S.empty()) S.pop();
 79     for(i=1;i<=cnt;i++) if(!in[i]) S.push(i);
 80     while(!S.empty())
 81     {
 82         u=S.top();
 83         S.pop();
 84         if(!col[u]) col[u]=1,col[conflict[u]]=2;
 85         for(v=1;v<=cnt;v++) if(map[u][v]&&--in[v]==0)
 86             S.push(v);
 87     }
 88 }
 89 
 90 void Cal()
 91 {
 92     int i;
 93     for(i=2;i<2*n;i+=2)
 94     {
 95         if(col[color[i]]==col[color[0]]) ans[i/2]=i;
 96         else ans[i/2]=i+1;
 97     }
 98 }
 99 
100 int TWO_ST()
101 {
102     int i;
103 
104     memset(dfn,0,sizeof(dfn));
105     memset(visit,0,sizeof(visit));
106     index=cnt=0;
107     while(!S.empty()) S.pop();
108     for(i=0;i<2*n;i++) if(!dfn[i]) Tarjan(i);
109 
110     for(i=0;i<n;i++)
111     {
112         if(color[2*i]==color[2*i+1]) return 0;
113         conflict[color[2*i]]=color[2*i+1];
114         conflict[color[2*i+1]]=color[2*i];
115     }
116     
117     Build();
118     Topsort();
119     Cal();
120     return 1;
121 }
122   

 

 

你可能感兴趣的:(2-st学习笔记)