CF1385E【Directing Edges】 (拓扑排序)

CF2000分图论

题意:给你一个n个顶点m条边的图,其中一些边没有方向,其余边有方向,让你对每一条没有方向的边赋一个方向,要求最终图不能形成自环。(没有重边)

题解:首先先看有方向的边所构成的图原本是否已经成环,如果成环的话必定直接输出NO,不成环的话则必定输出YES。统计每个点的indeg,进行拓扑排序,按照拓扑序的dfn顺序,把无向边的u和v两个点连线方向从拓扑序小的指向拓扑序大的。这样必定不会成环(这是拓扑排序的性质之一)

AC代码:

CF1385E【Directing Edges】 (拓扑排序)
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=2e5+5;
int tot,head[maxn];
struct E{
    int to,next;
}edge[maxn<<1];
void add(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int n,m,indeg[maxn],dfn[maxn];
bool topsort(){
    queue<int> q;int ct=0;
    rep(i,1,n) if(!indeg[i]) q.push(i);
    while(!q.empty()){
        int now=q.front();q.pop();
        dfn[now]=++ct;
        for(int i=head[now];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(--indeg[v]==0) q.push(v);
        }
    }
    if(ct!=n) return false;
    else return true;
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        mem(indeg,0),mem(head,-1),tot=0;
        vector<pair<int,int> >vec;
        vector<pair<int,int> >lol;
        rep(i,1,m){
            int op,u,v;scanf("%d%d%d",&op,&u,&v);
            if(!op){
                vec.pb({u,v});
            }else{
                add(u,v);indeg[v]++;
                lol.pb({u,v});
            }
        }
        if(!topsort()){puts("NO");continue;}
        else{
            puts("YES");
            for(auto it:vec){
                int a=it.first,b=it.second;
                if(dfn[a]>dfn[b]) swap(a,b);
                printf("%d %d\n",a,b);
            }
        }
        for(auto it:lol){
            printf("%d %d\n",it.first,it.second);
        }
    }
}
View Code

 

上一篇:E - Minimum Spanning Tree Gym - 102220E (转化+贡献)


下一篇:常用十大算法(七)— 克鲁斯卡尔算法