生活随笔
收集整理的這篇文章主要介紹了
CF1385E Directing Edges 拓扑序
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
題意:
給你一個圖和若干個邊,有些是有向邊,有些是無向邊,讓你給無向邊定向,使得最終的圖是DAGDAGDAG。
思路:
題目讓構造DAGDAGDAG,比較容易想到拓撲序。
首先我們需要知道拓撲圖中的點都是從拓撲序小的指向拓撲序大的,所以我們就可以根據這個連邊。
在原來有向圖上做一遍拓撲排序,有環的話直接無解就好啦,否則我們就按照拓撲序小的向拓撲序大的連邊,這樣一定可以保證是正確的。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=1000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
;
int d
[N
],dag
[N
];
vector
<int>v
[N
];
struct Edge {int a
,b
,op
;
}edge
[N
];bool check() {int id
=0;queue
<int>q
; for(int i
=1;i
<=n
;i
++) if(!d
[i
]) q
.push(i
);while(q
.size()) {int u
=q
.front(); q
.pop();dag
[u
]=++id
;for(auto x
:v
[u
]) {if(--d
[x
]==0) q
.push(x
);}}if(id
!=n
) return false;puts("YES");for(int i
=1;i
<=m
;i
++) {if(edge
[i
].op
) {printf("%d %d\n",edge
[i
].a
,edge
[i
].b
);continue;}if(dag
[edge
[i
].a
]<dag
[edge
[i
].b
]) printf("%d %d\n",edge
[i
].a
,edge
[i
].b
);else printf("%d %d\n",edge
[i
].b
,edge
[i
].a
);}return true;
}int main()
{
int _
; cin
>>_
;while(_
--) {scanf("%d%d",&n
,&m
);for(int i
=1;i
<=n
;i
++) d
[i
]=0,v
[i
].clear();for(int i
=1;i
<=m
;i
++) {scanf("%d%d%d",&edge
[i
].op
,&edge
[i
].a
,&edge
[i
].b
);if(edge
[i
].op
) v
[edge
[i
].a
].pb(edge
[i
].b
),d
[edge
[i
].b
]++;}if(!check()) puts("NO");}return 0;
}
總結
以上是生活随笔為你收集整理的CF1385E Directing Edges 拓扑序的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。