您的位置:首页 > 其它

Kattis-Chess Tournament(有向图判环)

2017-09-23 21:38 302 查看

题目链接:点击打开链接

题目大意:
给定一些标号,与标号之间的大小关系,判断所有给出的关系是否能同时成立。
解题思路:
其实看到题目就觉得是一个判断是否存在环的问题,但是有点区别就是点与点之间可以有相等的关系,这样的话就貌似不好直接判环:我当时是想非等于关系用单向边连接,而相等关系用双向边连接,然而实际上没什么卵用,等于关系直接成环了...。后面看了标程才知道自己的理解还是很肤浅啊:相等的关系其级别相同,那么我们把所有在同一个级别的点标一个编号,把所有的点重新标号后,根据原来点与点之间的关系在新的编号之间连边。假如有这样的一些关系:1=2=3=4,5=6=7,2>5,3>7,6>2,首先编号:(1,2,3,4)在一个级别,编号为1,(5,6,7)在一个级别,标号为2,则2>5,3>7,6>2
分别为1->2,1->2,2->1,其他情况以此类推。可以想到这样建成的一个新的图,就可以直接进行判环了。
代码:
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=5e4+10;
vector<int>equ[maxn];
vector<int>gre[maxn];
vector<int>Gra[maxn];
int vis[maxn];
int Newlv[maxn];
int n,m;
void Getlv(int u,int lv){
if(vis[u])return;
Newlv[u]=lv;
vis[u]=1;
int sz=equ[u].size();
for(int i=0;i<sz;i++){
int v=equ[u][i];
Getlv(v,lv);
}
}
int ok=1;
bool Top_sort(int u){
vis[u]=-1;
for(int i=0;i<Gra[u].size();i++){
int v=Gra[u][i];
if(vis[v]==-1)return false;
else if(!vis[v]&&!Top_sort(v))return false;
}
vis[u]=1;
return true;
}
int main(){
cin.tie(0);
ios_base::sync_with_stdio(0);
//   freopen("in.txt","r",stdin);
int x,y;
char ch;
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>x>>ch>>y;
if(ch=='='){
equ[x].push_back(y);
equ[y].push_back(x);
}
else gre[x].push_back(y);
}
int lv=0;
for(int i=0;i<n;i++){
if(!vis[i]){
Getlv(i,lv);++lv;
}
}
for(int i=0;i<n;i++){
int sz=gre[i].size();
for(int j=0;j<sz;j++){
int k=gre[i][j];
int u=Newlv[i],v=Newlv[k];
Gra[u].push_back(v);
}
}
memset(vis,0,sizeof vis);
for(int i=0;i<lv;i++){
if(!vis[i]){
if(!Top_sort(i)){ok=0;break;}
}
}
if(ok)cout<<"consistent\n";
else cout<<"inconsistent\n";
return 0;
}


其实做这个题以前并没有很仔细地去看拓扑排序,然后每次就直接抄模板。大概看了题解之后,就直接DFS去搜了一遍——WA...,然后想想才明白有向图判环和无向图判环的区别:一个可以重复搜到同一个点,只要这个点已经出栈了;一个只要搜到同一个点,就可以判断有环。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图论 判环