当前位置: 代码迷 >> 综合 >> Codeforces Round #656 E. Directing Edges
  详细解决方案

Codeforces Round #656 E. Directing Edges

热度:65   发布时间:2024-02-02 09:31:59.0

题目链接


题目大意:

给n个点和m条边,在接下来的m行输入t,x,y三个数,如果t==0则说明边是无向边,否则表示有向边,方向有x->y,问你能不能在保证图中无环的情况下,将无向边变成有向边,如果能输出YES,同时输出所有边,否则输出NO

解题思路:

在输入边的时候分别记录下有向边和无向边,如果是有向边,则存入vector中留着做拓扑排序,无向边则只需要记录下来,因为无向边对拓扑排序没有贡献,然后对图做一次拓扑排序,将每个点标记拓扑序,最后输出无向边的时候只要由拓扑序小的指向拓扑序大的即可

代码:

#include<bits/stdc++.h>using namespace std;const int maxn = 2e5+5;template <typename T>inline void read(T& t){char c=getchar();t=0;int f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c))t=t*10+c-48,c=getchar();t=f*t;
}template <typename T,typename... Args> inline void read(T& t,Args&... args){read(t);read(args...);
}int n,m,vis[maxn],in[maxn],ans[maxn];
int instd[maxn],outstd[maxn];
vector<int>e[maxn];void init(){for(int i=0;i<=n;i++){e[i].clear();in[i]=0;ans[i]=0;}memset(vis,0,sizeof vis);memset(instd,0,sizeof instd);memset(outstd,0,sizeof outstd);
}bool top_sort(){queue<int> q;for(int i=1;i<=n;i++){if(!in[i])q.push(i);}int tops=0;while(!q.empty()){int now=q.front();q.pop();ans[now]=++tops;for(int i=0;i<e[now].size();i++){int v=e[now][i];in[v]--;if(!in[v]){q.push(v);}}}return tops==n?true:false;//判断环
}int main(){int t;read(t);while(t--){read(n,m);init();for(int i=1;i<=m;i++){int tmp,x,y;read(tmp,x,y);instd[i]=x;outstd[i]=y;if(tmp){vis[i]=1;e[x].emplace_back(y);in[y]++;}}if(!top_sort()){puts("NO");continue;}puts("YES");for(int i=1;i<=m;i++){if(vis[i]||ans[instd[i]]<ans[outstd[i]]){printf("%d %d\n",instd[i],outstd[i]);}else{printf("%d %d\n",outstd[i],instd[i]);}}}return 0;
}
  相关解决方案