「NOIP模拟赛」混合图
Hzwer神犇最近又征服了一个国家,然后接下来却也遇见了一个难题。
Hzwer的国家有n个点,m条边,而作为国王,他十分喜欢游览自己的国家。他一般会从任意一个点出发,随便找边走,沿途欣赏路上的美景。但是我们的Hzwer是一个奇怪的人,他不喜欢走到自己以前走过的地方,他的国家本来有p1条有向边,p2条无向边,由于国王奇怪的爱好,他觉得整改所有无向边,使得他们变成有向边,要求整改完以后保证他的国家不可能出现从某个地点出发顺着路走一圈又回来的情况。(注:m=p1+p2.)
概述:给你一张混合图,要求你为无向图定向,使得图上没有环。
「输入格式」 dizzy.in
第一行3个整数 n,p1,p2,分别表示点数,有向边的数量,无向边的数量。
第二行起输入p1行,每行2个整数 a,b 表示a到b有一条有向边。
接下来输入p2行,每行2个整数 a,b 表示a和b中间有一条无向边。
「输出格式」 dizzy.out
对于每条无向边,我们要求按输入顺序输出你定向的结果,也就是如果你输出a b,那表示你将a和b中间的无向边定向为a->b。
注意,也许存在很多可行的解。你只要输出其中任意一个就好。
「样例输入」
4 2 3
1 2
4 3
1 3
4 2
3 2
「样例输出」
1 3
4 2
2 3
数据范围
对于20%的数据 n<=10 p1<=10 p2<=5
对于30%的数据 n<=10 p1<=30 p2<=20
对于100%的数据 n<=100000 p1<=100000 p2<=100000
数据保证至少有一种可行解。
题解
把所有有向边拓扑排序后,每条无向边的方向就是从拓扑序小的连向大的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #define inf 0x7fffffff #define ll long long using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,p1,p2,cnt,top,tot; int head[100005],r[100005]; int q[100005],s[100005],h[100005]; struct data{int to,next;}e[100005]; void insert(int u,int v) {e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;} void topsort() { for(int i=1;i<=n;i++) if(!r[i]){s[++top]=i;q[++tot]=i;} while(top) { int x=s[top--]; for(int i=head[x];i;i=e[i].next) { r[e[i].to]--; if(!r[e[i].to]){s[++top]=e[i].to;q[++tot]=e[i].to;} } } } int main() { //freopen("dizzy.in","r",stdin); //freopen("dizzy.out","w",stdout); n=read();p1=read();p2=read(); for(int i=1;i<=p1;i++) { int u=read(),v=read(); insert(u,v); r[v]++; } topsort(); for(int i=1;i<=n;i++) h[q[i]]=i; for(int i=1;i<=p2;i++) { int u=read(),v=read(); if(h[u]>=h[v])printf("%d %d\n",v,u); else printf("%d %d\n",u,v); } return 0; } |
计算入队顺序这里有错吧