zoukankan      html  css  js  c++  java
  • CF1385E Directing Edges 题解

    题目大意

    给定一张 (n) 个点,(m) 条边的图 (G),其中一部分边是有向边,一部分边是无向边。需要给所有给无向边定向,使得组成的新图是一个 DAG。

    多测,(Tleq 2 imes10^4)(sum n,sum mleq 2 imes 10^5)

    符号及约定

    (operatorname{edge}(u,v)) 表示节点 (u)(v) 之间的边。(u o v) 表示一条从 (u)(v) 的有向边。

    Solution

    先忽视所有无向边。如果剩余的所有有向边不能组成 DAG,那么无论无向边怎么定向也没用。

    接下来考虑有向边没有问题时如何构造可行解即可。

    不妨对有向边组成的 DAG 进行 topo sort,得到第 (i) 个节点的 topo sort 序不妨记为 (operatorname{ord}(i))

    任取一条无向边 (operatorname{edge}(u,v)),不妨令 (operatorname{ord}(u)<operatorname{ord}(v))(反正是无向边,并且方向待定,没有区别)。那么直接令 (operatorname{edge}(u,v)=u o v) 即可。原因是因为 (forall u,vin G')(这里 (G') 是一个 DAG)满足 (operatorname{ord}(u)<operatorname{ord}(v)),则不存在 (v o u) 这条边。

    我们不妨形象地将 topo sort 所得的点序排列成一行,从左到右分别为 (operatorname{ord}(u)=1,2,3,...,n) 的节点。那么已经存在的构成 DAG 的边必然通通指向右边。

    接下来我们也只需要保证我们所连的边也朝右,那么必然不可能存在环。

    代码

    #include<bits/stdc++.h>
    #define HohleFeuerwerke using namespace std
    #pragma GCC optimize(3,"Ofast","-funroll-loops","-fdelete-null-pointer-checks")
    #pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
    #define int long long
    HohleFeuerwerke;
    inline int read(){
    	int s=0,f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) s=s*10+c-'0';
    	return s*f;
    }
    inline void write(int x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>=10) write(x/10);
    	putchar('0'+x%10);
    }
    const int MAXN=1e6+5;
    int T,n,m,cntEdge,head[MAXN],ind[MAXN];
    struct edge{
    	int type;
    	int from,to,next;
    }e[MAXN];
    vector<int> topo;
    int refl[MAXN];
    inline void add(int t,int u,int v){
    	cntEdge++; e[cntEdge].type=t;
    	e[cntEdge].from=u,e[cntEdge].to=v;
    	e[cntEdge].next=head[u],head[u]=cntEdge;
    }
    deque<int> q;
    inline bool bfs(){
    	for(int i=1;i<=n;i++){
    		if(ind[i]==0) q.push_back(i);
    	}
    	while(!q.empty()){
    		int u=q.front(); q.pop_front();
    		topo.push_back(u);
    		for(int i=head[u];i;i=e[i].next){
    			if(e[i].type==1){
    				int v=e[i].to;
    				if(--ind[v]==0) q.push_back(v);
    			}
    		}
    	}
    	if(topo.size()==n) return true;
    	return false;
    }
    signed main()
    {
    	T=read();
    	while(T--){
    		n=read(),m=read(),cntEdge=0;
    		topo.clear(); q.clear();
    		for(int i=1;i<=n+5;i++) ind[i]=head[i]=refl[i]=0;
    		for(int i=1;i<=m;i++){
    			int type=read();
    			int u=read(),v=read();
    			if(type==1) add(1,u,v),ind[v]++;
    			else add(0,u,v);
    		}
    		if(bfs()){
    			puts("YES");
    			for(int i=1;i<=n;i++) refl[topo[i-1]]=i;
    			for(int i=1;i<=m;i++){
    				if(e[i].type==0){
    					if(refl[e[i].to]<refl[e[i].from])	
    						write(e[i].to),putchar(' '),write(e[i].from),puts("");
    					else write(e[i].from),putchar(' '),write(e[i].to),puts("");
    				}
    				else write(e[i].from),putchar(' '),write(e[i].to),puts("");
    			}
    		}
    		else puts("NO");
    	}
    }
    
  • 相关阅读:
    pandas--对axis=0,axis=1的理解
    启动secondarynamenode时报错
    5月27日经历问题(在有框架的情况下从无到有增加一套功能)
    5.21工作记录(修改页面跳转,去掉多余的js;增加图片清除功能)
    工作记录520
    5月14日经历问题
    idea快捷键
    Linux下常用redis指令
    初识lunix
    Redis
  • 原文地址:https://www.cnblogs.com/AllWeKnow/p/15521717.html
Copyright © 2011-2022 走看看