题目大意:给出一堆关系类似”A<B”,有三种结果:1)在第k个关系读入后出现环路,2)在第k个关系读入后能够确定排序,3)无法确定顺序。
注意:
1、出现结果1、2之后之后的s要读但是操作略过
2、要判断重复的边(入度不能重复加)
3、要先判断环路再判断是否有多个入度为0的点(即没有全部排序)
#include<iostream>
#include<string.h>
#include<string>
#include<queue>
using namespace std;
int n,m,ans,opt;
bool g[27][27];
int gin[27];
char sortout[27];
int top;
bool topo(int c)
{
queue<int> Q;
int i,u,tin[27];
bool unsure=false;
for (i=1;i<=n;i++)
if (gin[i]==0)
Q.push(i);
top=0;
memcpy(tin,gin,sizeof(gin));
while(!Q.empty())
{
if (Q.size()>1)
unsure=true;//多个入度为1,肯定没有全部排序
u=Q.front();Q.pop();
sortout[top++]=u+'A'-1;
for (i=1;i<=n;i++)
if (g[u][i])
{
tin[i]--;
if (tin[i]==0)
Q.push(i);
}
}
//注意先判断环路,才判断无结果!
if (top<n)//节点没有输出完就已经没有入度为0的点则有环
{ opt=2;ans=c;return 1; }
else if (unsure)
return 0;
else//top==n
{ opt=1;ans=c;return 1; }
return 0;
}
void solve()
{
int i,a,b;
string s;
bool flag=false;
memset(g,0,sizeof(g));
memset(gin,0,sizeof(gin));
for (i=1;i<=m;i++)
{
cin>>s;
if (flag)
continue;
a=s[0]-'A'+1;b=s[2]-'A'+1;
if (g[b][a])//有环
{
opt=2;ans=i;
flag=true;continue;
}
if (!g[a][b])//判断之前是否插入过该条边
{
g[a][b]=true;
gin[b]++;
}
flag=topo(i);
}
if (!flag)
opt=3;
}
int main()
{
int i;
while(cin>>n>>m)
{
if (n==0&&m==0)
break;
solve();
if (opt==1)
{
cout<<"Sorted sequence determined after "<<ans<<" relations: ";
for (i=0;i<top;i++) cout<<sortout[i];
cout<<"."<<endl;
}
else if (opt==2)
cout<<"Inconsistency found after "<<ans<<" relations."<<endl;
else cout<<"Sorted sequence cannot be determined."<<endl;
}
return 0;
}
题目大意:给任务排序,并输出顺序。
ps:还是使用贪心比较好,DFS比较耗时
贪心解法:
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
int n,m;
bool g[101][101];
int gin[101];
int c[101];
int top;
void topo()
{
int i;
int u;
top=0;
queue<int> Q;
for (i=1;i<=n;i++)
if (gin[i]==0)
Q.push(i);
while(!Q.empty())
{
u=Q.front();Q.pop();
c[top++]=u;
for (i=1;i<=n;i++)
{
if (g[u][i])
{
gin[i]--;
if (gin[i]==0)
Q.push(i);
}
}
}
}
int main()
{
int i,a,b;
while(cin>>n>>m)
{
if (n==0&&m==0)
break;
memset(g,0,sizeof(g));
memset(gin,0,sizeof(0));
for (i=0;i<m;i++)
{
cin>>a>>b;
g[a][b]=1;
gin[b]++;
}
topo();
for (i=0;i<top-1;i++)
cout<<c[i]<<" ";
cout<<c[i]<<endl;
}
return 0;
}
DFS解法:
//AC
#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
bool g[105][105]={0};
int n,m;
int c[200];
int topo[200], t;
bool dfs(int u)
{
c[u] = -1; //访问标志
for(int v = 1; v <= n; v++)
if(g[u][v])
{
if(c[v]<0) return false; //存在有向环,失败退出
else if(!c[v] && !dfs(v))
return false;
}
c[u] = 1; topo[--t]=u;
return true;
}
bool toposort( )
{
t = n;
memset(c, 0, sizeof(c));
for(int u = 1; u <= n; u++)
if(!c[u])
if(!dfs(u))
return false;
return true;
}
int main()
{
int i,j,x,y,count,point;
while(cin>>n>>m)
{
if (n==0 && m==0)
break;
memset(g,0,sizeof(g));
for (i=1;i<=m;i++)
{
cin>>x;cin>>y;
g[x][y]=1;
}
toposort();
for (i=0;i<n-1;i++)
cout<<topo[i]<<" ";
cout<<topo[i]<<endl;
}
return 0;
}