牢记:拓扑排序得出的ans是一个序列
思路:确定正向or逆向排序 ; 入度为0入队列,队列里的都是答案,每一个答案对应的边顶点 --入度,为0入队列
来模板(第一题)
复杂度O(n+e)
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <map>
#include <algorithm>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
const int MAXN=505;
int indegree[MAXN];
vector <int> edge[MAXN];
void init(int n)
{
memset(indegree,0,sizeof(indegree));
for(int i=1;i<=n;i++) edge[i].clear();
}
int main(void)
{
int n,m;
while((scanf("%d%d",&n,&m))==2)
{
init(n);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
indegree[y]++;
edge[x].push_back(y);
}
vector <int> ans;
priority_queue <int,vector<int>,greater<int> >temp;
for(int i=1;i<=n;i++)
if(indegree[i]==0) temp.push(i);
while(!temp.empty())
{
int v=temp.top();temp.pop();
ans.push_back(v);
for(int i=0;i<edge[v].size();i++)
if(--indegree[edge[v][i]]==0) temp.push(edge[v][i]);
}
for(int i=0;i<ans.size();i++)
{
if(i!=ans.size()-1) printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
}
}
常见问题: 1.是否有环(有向图topsort/无向图并查集)
2.反向拓扑(一定大小关系,小的尽量考前)
3.拓扑排序的唯一解问题
1:HDU-1285
题意:已知有n个队伍,m个关系对(X在Y前面),输出一个解
思路:基础拓扑
2:HDU-3342
题意/思路:与上雷同
3:HDU-2647
题意:n个人,m个关系(X的工资比Y高,基础工资均为888),问至少要付多少工资
思路:反向拓扑indegree[y]++,edge[x].push_back(x)
4:HDU-4857
题意:n个人,m对关系(x<y)并且小的尽量考前
思路:反向拓扑+优先队列(大的优先) , 反向输出
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <map>
#include <algorithm>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
const int MAXN=30000+5;
int indegree[MAXN];
vector <int> edge[MAXN];
void init(int n)
{
memset(indegree,0,sizeof(indegree));
for(int i=1;i<=n;i++) edge[i].clear();
}
int main(void)
{
int n,m;
int t;
cin >>t;
while(t--)
{
cin >>n >>m;
init(n);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
indegree[x]++;
edge[y].push_back(x);
}
vector <int> ans;
priority_queue <int> temp;
for(int i=1;i<=n;i++)
if(indegree[i]==0) temp.push(i);
while(!temp.empty())
{
int v=temp.top();temp.pop();
ans.push_back(v);
for(int i=0;i<edge[v].size();i++)
if(--indegree[edge[v][i]]==0) temp.push(edge[v][i]);
}
for(int i=ans.size()-1;i>=0;i--)
{
if(i!=0) printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
}
}
5:HDU-5222
题意:给一个有向边和无向边组成的图,问是否存在环
思路:有向图topsort+考虑并查集 / 无向图并查集
6:HDU-3687
题意/思路:雷同HDU-4857
7:POJ-2367
题意/思路:雷同1,是最基础的拓扑。
8.POJ-1094
题意:给定n和m(m对关系,a<b表示a要在b前面),输出是否矛盾;不矛盾的话 是否有唯一解? 矛盾和唯一解的情况输出由第几条信息判断完毕。
思路:每次输入一组数据都要topsort一次,判断是否矛盾就是判断是否有环。唯一解的要求是在每次入队列的时候,que.size()==1,即每次寻找入度为0的并且没vis过的,只有一个。
#include <stdio.h>
#include <map>
#include <vector>
#include <queue>
#include <iostream>
#define bug cout <<"woc"<<endl
using namespace std;
const int MAXN=100;
int indegree[MAXN];
vector <int> edge[MAXN];
int indegreerecord[MAXN];
vector<int> edgerecord[MAXN];
int l;
void comeback(int n)
{
for(int i=1;i<=n;i++)
indegree[i]=indegreerecord[i];
for(int i=1;i<=n;i++)
{
edge[i].clear();
for(int j=0;j<edgerecord[i].size();j++)
{
edge[i].push_back(edgerecord[i][j]);
}
}
}
void init(int n)
{
for(int i=1;i<=n;i++)
indegree[i]=0,edge[i].clear(),indegreerecord[i]=0,edgerecord[i].clear();
}
int topsort(int n)
{
int cnt=0,sc=0;
bool flag=true;
vector <int> ans;
priority_queue <int>temp;
for(int i=1;i<=n;i++)
if(indegree[i]==0) temp.push(i);
//int c=temp.size();
//if(c==0) return -1;
//if(c>=2) return 0; //wa的地方,因为>=2可能会有矛盾的情况
//else
//{
while(!temp.empty())
{
cnt=0;
for(int i=1;i<=n;i++)
if(indegree[i]==0) cnt++;
if(cnt!=sc+1) flag=false;
else if(cnt==sc+1) sc++;
int v=temp.top();temp.pop();
ans.push_back(v);
for(int i=0;i<edge[v].size();i++)
if(--indegree[edge[v][i]]==0) temp.push(edge[v][i]);
}
//}
if(ans.size()!=n)
{
return -1;
}
else
{
if(flag==true)
{
printf("Sorted sequence determined after %d relations: ",l);
for(int i=0;i<ans.size();i++)
printf("%c",ans[i]+'A'-1);
printf(".\n");
return 1;
}
else return 0;
}
}
int main(void)
{
int n,m;
while(cin>>n>>m)
{
int flag=0;
if(n==0 && m==0) break;
init(n);
for(int i=1;i<=m;i++)
{
char str[5];
scanf("%s",str+1);
if(flag==-1 || flag==1) continue;l=i;
int x=str[1]-'A'+1;
int y=str[3]-'A'+1;
indegree[y]++;indegreerecord[y]++;
edge[x].push_back(y);edgerecord[x].push_back(y);
flag=topsort(n);
comeback(n);
}
if(flag==-1)
printf("Inconsistency found after %d relations.\n",l);
else if(flag==0)
printf("Sorted sequence cannot be determined.\n");
}
}
https://vjudge.net/contest/199005#overview