拓扑排序

有很多奇妙的题.....

题目VJ上做了些.

近期在POJ和HDU上做一些题,参考 http://blog.csdn.net/shahdza/article/details/7779389

HDU 1285 裸题不讲=w=很久以前用Vector建图的时候就A了......

HDU 2647 就是判断一下是否有拓扑序列(这个可以用强连通分量Tarjan做=w=但是拓扑排写起来比较简单...)

然后总代价就是按照排序层数(具体看程序,我们把能够同时存在于队列中的元素表上同一个dep)算....

  1 #include <cstdio>
  2 #include <fstream>
  3 #include <iostream>
  4  
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cmath>
  9  
 10 #include <queue>
 11 #include <vector>
 12 #include <map>
 13 #include <set>
 14 #include <stack>
 15 #include <list>
 16  
 17 typedef unsigned int uint;
 18 typedef long long int ll;
 19 typedef unsigned long long int ull;
 20 typedef double db;
 21  
 22 using namespace std;
 23  
 24 inline int getint()
 25 {
 26     int res=0;
 27     char c=getchar();
 28     bool mi=false;
 29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 31     return mi ? -res : res;
 32 }
 33 inline ll getll()
 34 {
 35     ll res=0;
 36     char c=getchar();
 37     bool mi=false;
 38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 40     return mi ? -res : res;
 41 }
 42 
 43 //==============================================================================
 44 //==============================================================================
 45 //==============================================================================
 46 //==============================================================================
 47 
 48 
 49 struct edge
 50 {
 51     int in;
 52     edge*nxt;
 53 }pool[20050];
 54 edge*et;
 55 edge*eds[10050];
 56 void addedge(int a,int b)
 57 { et->in=b; et->nxt=eds[a]; eds[a]=et++; }
 58 #define FOREACH_EDGE(i,j) for(edge*i=eds[j];i;i=i->nxt)
 59 
 60 
 61 int n,m;
 62 
 63 int dep[10050];
 64 int deg[10050];
 65 bool used[10050];
 66 
 67 
 68 int main()
 69 {    
 70     while(scanf("%d%d",&n,&m)>0)
 71     {
 72         et=pool;
 73         memset(eds,0,sizeof(edge*)*(n+1));
 74         memset(dep,0,sizeof(int)*(n+1));
 75         memset(deg,0,sizeof(int)*(n+1));
 76         memset(used,0,sizeof(bool)*(n+1));
 77         
 78         for(int i=0;i<m;i++)
 79         {
 80             int a=getint()-1;
 81             int b=getint()-1;
 82             addedge(b,a);
 83             deg[a]++;
 84         }
 85         
 86         queue<int> q;
 87         for(int i=0;i<n;i++)
 88         if(deg[i]==0) q.push(i);
 89         
 90         while(!q.empty())
 91         {
 92             int x=q.front(); q.pop();
 93             used[x]=true;
 94             FOREACH_EDGE(e,x)
 95             {
 96                 deg[e->in]--;
 97                 if(deg[e->in]==0)
 98                 {
 99                     dep[e->in]=dep[x]+1;
100                     q.push(e->in);
101                 }
102             }
103         }
104         
105         bool ok=true;
106         for(int i=0;i<n;i++)
107         if(!used[i]) { ok=false; break; }
108         
109         if(!ok)
110         {
111             printf("-1
");
112             continue;
113         }
114         
115         int res=0;
116         for(int i=0;i<n;i++)
117         res+=dep[i]+888;
118         
119         printf("%d
",res);
120     }
121     
122     return 0;
123 }
View Code

HDU 1811

判断是否存在拓扑序,以及是否存在确定的拓扑序.

判断是否存在,就是按照上面的,能把所有点压入队列就肯定存在可行拓扑序列.

(一般有环就说明限制条件存在矛盾,这个环中的任意一个节点都不能被压入队列)

拓扑序列只有一个的条件是每时每刻队列中仅有一个节点.(否则这两个节点的顺序不定.)

处理那个等号非常麻烦.三次提交都错在那里. 这个题看起来还可以用差分约束.

  1 #include <cstdio>
  2 #include <fstream>
  3 #include <iostream>
  4  
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cmath>
  9  
 10 #include <queue>
 11 #include <vector>
 12 #include <map>
 13 #include <set>
 14 #include <stack>
 15 #include <list>
 16  
 17 typedef unsigned int uint;
 18 typedef long long int ll;
 19 typedef unsigned long long int ull;
 20 typedef double db;
 21  
 22 using namespace std;
 23  
 24 inline int getint()
 25 {
 26     int res=0;
 27     char c=getchar();
 28     bool mi=false;
 29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 31     return mi ? -res : res;
 32 }
 33 inline ll getll()
 34 {
 35     ll res=0;
 36     char c=getchar();
 37     bool mi=false;
 38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 40     return mi ? -res : res;
 41 }
 42 
 43 //==============================================================================
 44 //==============================================================================
 45 //==============================================================================
 46 //==============================================================================
 47 
 48 struct edge
 49 {
 50     int in;
 51     edge*nxt;
 52 }pool[20050];
 53 edge*et;
 54 edge*eds[2][10050];
 55 void addedge(int i,int j,int k)
 56 { et->in=j; et->nxt=eds[k][i]; eds[k][i]=et++; }
 57 #define FOREACH_EDGE(i,j,f) for(edge*i=eds[f][j];i;i=i->nxt)
 58 
 59 //union find
 60 int f[10050];
 61 void INIT(int size)
 62 { for(int i=0;i<size;i++) f[i]=i; }
 63 int findf(int x)
 64 { return f[x]==x ? x : f[x]=findf(f[x]); }
 65 void connect(int a,int b)
 66 { f[findf(a)]=findf(b); }
 67 
 68 int block[10050];
 69 int btot;
 70 bool used[10050];
 71 int deg[10050];
 72 
 73 int n,m;
 74 
 75 int A[20050];
 76 int B[20050];
 77 char C[20050];
 78 
 79 int main()
 80 {
 81     while(scanf("%d%d",&n,&m)>0)
 82     {
 83         INIT(n+1);
 84         memset(eds[1],0,sizeof(edge*)*(n+1));
 85         memset(block,0xFF,sizeof(int)*(n+1));
 86         et=pool;
 87         btot=0;
 88         
 89         bool unc=false;
 90         bool conf=false;
 91         
 92         for(int i=0;i<m;i++)
 93         {
 94             scanf("%d %c %d",&A[i],&C[i],&B[i]);
 95             if(C[i]=='=') connect(A[i],B[i]);
 96         }
 97         
 98         for(int i=0;i<m;i++)
 99         if(C[i]!='=')
100         {
101             if(findf(A[i])==findf(B[i])) conf=true;
102             
103             if(C[i]=='>') addedge(A[i],B[i],1);
104             else if(C[i]=='<') addedge(B[i],A[i],1);
105         }
106         
107         if(conf) { printf("CONFLICT
"); continue; }
108         
109         for(int i=0;i<n;i++)
110         {
111             if(block[findf(i)]==-1)
112             block[findf(i)]=btot++;
113             block[i]=block[findf(i)];
114         }
115         
116         memset(eds[0],0,sizeof(edge*)*(btot+1));
117         memset(deg,0,sizeof(int)*(btot+1));
118         memset(used,0,sizeof(bool)*(btot+1));
119         
120         for(int i=0;i<n;i++)
121         FOREACH_EDGE(e,i,1)
122         if(block[i]!=block[e->in])
123         {
124             addedge(block[i],block[e->in],0);
125             deg[block[e->in]]++;
126         }
127         
128         queue<int> q;
129         for(int i=0;i<btot;i++)
130         if(deg[i]==0) q.push(i);
131         
132         while(!q.empty())
133         {
134             if(q.size()>1) unc=true;
135             int x=q.front(); q.pop();
136             used[x]=true;
137             FOREACH_EDGE(e,x,0)
138             {
139                 deg[e->in]--;
140                 if(deg[e->in]==0)
141                 q.push(e->in);
142             }
143         }
144         
145         for(int i=0;i<btot;i++)
146         if(!used[i]) { conf=true; break; }
147         
148         if(conf) printf("CONFLICT
");
149         else if(unc) printf("UNCERTAIN
");
150         else printf("OK
");
151         
152     }
153     
154     return 0;
155 }
View Code

POJ 3287

裸的拓扑标号. 要求优先级.

做的时候,把边反向,做拓扑排序,然后逆序标号.

千万想清楚程序在干什么! 这道题是 "对标号进行限制" 以及 "对每个标号进行赋权" 然后 "输出标号的权值".

  1 #include <cstdio>
  2 #include <fstream>
  3 #include <iostream>
  4  
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cmath>
  9  
 10 #include <queue>
 11 #include <vector>
 12 #include <map>
 13 #include <set>
 14 #include <stack>
 15 #include <list>
 16  
 17 typedef unsigned int uint;
 18 typedef long long int ll;
 19 typedef unsigned long long int ull;
 20 typedef double db;
 21  
 22 using namespace std;
 23  
 24 inline int getint()
 25 {
 26     int res=0;
 27     char c=getchar();
 28     bool mi=false;
 29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 31     return mi ? -res : res;
 32 }
 33 inline ll getll()
 34 {
 35     ll res=0;
 36     char c=getchar();
 37     bool mi=false;
 38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 40     return mi ? -res : res;
 41 }
 42  
 43 db eps=1e-20;
 44 inline bool feq(db a,db b)
 45 { return fabs(a-b)<eps; }
 46 
 47 template<typename Type>
 48 inline Type avg(const Type a,const Type b)
 49 { return a+((b-a)/2); }
 50 
 51 //==========================================================
 52 //==========================================================
 53 //==========================================================
 54 //==========================================================
 55 
 56 
 57 struct edge
 58 {
 59     int in;
 60     edge*nxt;
 61 }pool[40050];
 62 edge*et=pool;
 63 edge*eds[205];
 64 void addedge(int a,int b)
 65 { et->in=b; et->nxt=eds[a]; eds[a]=et++; }
 66 #define FOREACH_EDGE(i,j) for(edge*i=eds[j];i;i=i->nxt)
 67 
 68 
 69 int n,m;
 70 int deg[205];
 71 int label[205];
 72 
 73 int main()
 74 {
 75     int T=getint();
 76     while(T--)
 77     {
 78         n=getint();
 79         m=getint();
 80         
 81         memset(eds,0,sizeof(edge*)*(n+1));
 82         memset(deg,0,sizeof(int)*(n+1));
 83         memset(label,0,sizeof(int)*(n+1));
 84         et=pool;
 85         
 86         int tot=0;
 87         
 88         for(int i=0;i<m;i++)
 89         {
 90             int a=getint()-1;
 91             int b=getint()-1;
 92             addedge(b,a);
 93             deg[a]++;
 94         }
 95         
 96         priority_queue<int> q;
 97         for(int i=0;i<n;i++)
 98         if(deg[i]==0) q.push(i);
 99         
100         while(!q.empty())
101         {
102             int x=q.top(); q.pop();
103             label[x]=n-(tot++);
104             FOREACH_EDGE(e,x)
105             {
106                 deg[e->in]--;
107                 if(deg[e->in]==0)
108                 q.push(e->in);
109             }
110         }
111         
112         if(tot!=n) printf("-1
");
113         else
114         {
115             printf("%d",label[0]);
116             for(int i=1;i<n;i++)
117             printf(" %d",label[i]);
118             printf("
");
119         }
120     }
121     
122     return 0;
123 }
View Code

POJ 1270

枚举拓扑序并输出.

首先读入比较坑.....WA掉一次的原因是没排序...题目要求不是按照读入的字典序而是字母字典序.....果断写了个冒泡上去......然后就A了.....

这个算是拓扑排序么?唉随便吧....

  1 #include <cstdio>
  2 #include <fstream>
  3 #include <iostream>
  4  
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cmath>
  9  
 10 #include <queue>
 11 #include <vector>
 12 #include <map>
 13 #include <set>
 14 #include <stack>
 15 #include <list>
 16  
 17 typedef unsigned int uint;
 18 typedef long long int ll;
 19 typedef unsigned long long int ull;
 20 typedef double db;
 21  
 22 using namespace std;
 23  
 24 inline int getint()
 25 {
 26     int res=0;
 27     char c=getchar();
 28     bool mi=false;
 29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 31     return mi ? -res : res;
 32 }
 33 inline ll getll()
 34 {
 35     ll res=0;
 36     char c=getchar();
 37     bool mi=false;
 38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 40     return mi ? -res : res;
 41 }
 42 
 43 //==========================================================
 44 //==========================================================
 45 //==========================================================
 46 //==========================================================
 47 
 48 
 49 struct edge
 50 {
 51     int in;
 52     edge*nxt;
 53 }pool[40050];
 54 edge*et=pool;
 55 edge*eds[205];
 56 void addedge(int a,int b)
 57 { et->in=b; et->nxt=eds[a]; eds[a]=et++; }
 58 #define FOREACH_EDGE(i,j) for(edge*i=eds[j];i;i=i->nxt)
 59 
 60 int n,m;
 61 
 62 char inp1[105];
 63 int pos[256];
 64 char inp2[1050];
 65 
 66 int deg[105];
 67 
 68 int cur[105];
 69 bool ins[105];
 70 void DFS(int dep)
 71 {
 72     if(dep==n)
 73     {
 74         for(int i=0;i<n;i++) printf("%c",inp1[cur[i]]);
 75         printf("
");
 76         return ;
 77     }
 78     
 79     for(int i=0;i<n;i++)
 80     if(!ins[i] && deg[i]==0)
 81     {
 82         cur[dep]=i;
 83         ins[i]=true;
 84         FOREACH_EDGE(e,i) deg[e->in]--;
 85         DFS(dep+1);
 86         FOREACH_EDGE(e,i) deg[e->in]++;
 87         ins[i]=false;
 88     }
 89 }
 90 
 91 int main()
 92 {
 93     while(true)
 94     {
 95         gets(inp1);
 96         if(feof(stdin)) break;
 97         gets(inp2);
 98         
 99         {
100             n=0;
101             int p=0; 
102             while(inp1[p]!=0)
103             {
104                 if('a'<=inp1[p] && inp1[p]<='z') 
105                 pos[inp1[p]]=n,inp1[n++]=inp1[p];
106                 p++;
107             }
108             
109             for(int i=0;i<n;i++)
110             for(int j=i+1;j<n;j++)
111             if(inp1[i]>inp1[j])
112             swap(inp1[i],inp1[j]),swap(pos[inp1[i]],pos[inp1[j]]);
113             
114         }
115         
116         et=pool;
117         memset(eds,0,sizeof(int)*(n+1));
118         memset(deg,0,sizeof(int)*(n+1));
119         
120         {
121             int p=0;
122             int c=0;
123             char a;
124             while(inp2[p]!=0)
125             {
126                 if('a'<=inp2[p] && inp2[p]<='z')
127                 {
128                     if(c==1)
129                     {
130                         addedge(pos[a],pos[inp2[p]]);
131                         deg[pos[inp2[p]]]++;
132                         c=0;
133                     }
134                     else a=inp2[p],c++;
135                 }
136                 
137                 p++;
138             }
139         }
140         
141         DFS(0);
142         
143         printf("
");
144     }
145     
146     return 0;
147 }
View Code
原文地址:https://www.cnblogs.com/DragoonKiller/p/4451821.html