标签:
Description
Input
Output
Sample Input
5 2 4 3 0 4 5 0 0 0 1 0
Sample Output
1 2
今天模拟赛的第一题
题意是给一个图,第一问求最少选多少个点,使得从这些点出发能遍历整张图。第二问是最少添加多少有向边,使得整个图变成强连通图
第一问比较sb。tarjan缩点完入度为0的点的个数
第二问有点坑……令G{E,V}表示某一弱连通图,I(G)表示G中入度为0的点的个数,O(G)表示G中出度为0的点的个数。
原来我以为是Σmax(I(i),O(i))。其实是max(ΣI(i),ΣO(i))。这区别很容易看出来吧
#include<cstdio> #include<iostream> #define LL long long using namespace std; inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } struct edge{int to,next;}e[1000010]; int n,cnt,cnt3,tt,sumi,sumo; int head[100010]; bool inset[100010]; int dfn[100010],low[100010]; int zhan[100010],top; int belong[100010]; int I[100010],O[100010]; inline void ins(int u,int v) { e[++cnt].to=v; e[cnt].next=head[u]; head[u]=cnt; } inline void dfs(int x) { zhan[++top]=x;inset[x]=1; dfn[x]=low[x]=++tt; for (int i=head[x];i;i=e[i].next) { if (!dfn[e[i].to]) { dfs(e[i].to); low[x]=min(low[x],low[e[i].to]); }else if (inset[e[i].to]) low[x]=min(low[x],dfn[e[i].to]); } if (low[x]==dfn[x]) { cnt3++; int p=-1; while (p!=x) { p=zhan[top--]; belong[p]=cnt3; inset[p]=0; } } } inline void tarjan() {for (int i=1;i<=n;i++)if (!dfn[i]) dfs(i);} int main() { n=read(); for (int i=1;i<=n;i++) { int x; while (scanf("%d",&x)&&x)ins(i,x); } tarjan(); for (int i=1;i<=n;i++) { for (int j=head[i];j;j=e[j].next) if (belong[i]!=belong[e[j].to]) { O[belong[i]]++; I[belong[e[j].to]]++; } } if (cnt3==1) { printf("1\n0\n"); return 0; } for (int i=1;i<=cnt3;i++) { if (!I[i])sumi++; if (!O[i])sumo++; } printf("%d\n%d\n",sumi,max(sumi,sumo)); return 0; }
标签:
原文地址:http://www.cnblogs.com/zhber/p/4175862.html