题目(vijos)
这题把样例画一画就可以明白:只有在环上的点才有机会结束游戏(也就是从别人那里得到自己生日的信息)。
所以这题就是求环,环上点的个数就是游戏局数。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
你以为就这么简单?Worng!
如果是下面这张图这样呢?
所以!这道题是要求环,但是要求最小环!
用Tarjan跑一遍就可以了。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> #include <cmath> #include <stack> using namespace std; int n,t; bool vis[200005]; int dfn[200005],low[200005]; int idx; struct edge{ int vk; int next; }e[200005]; int k=1,head[200005]; stack <int> s; void ad(int u,int v) { e[k].vk=v; e[k].next=head[u]; head[u]=k++; } bool flag=false; int cnt; int ans=999999999; void tarjan(int u) { int v; dfn[u]=low[u]=++idx; s.push(u); vis[u]=1; for (int i=head[u];i;i=e[i].next) { v=e[i].vk; if (!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if (vis[v]) low[u]=min(low[u],dfn[v]); } if (dfn[u]==low[u]) { int tmp=0; cnt++; while (v!=u) { v=s.top(); s.pop(); tmp++; vis[v]=0; } if (tmp!=1) ans=min(ans,tmp); } } int main() { scanf( for (register int i=1;i<=n;++i) { scanf( ad(i,t); } for (int i=1;i<=n;++i) { if (!dfn[i]) tarjan(i); } printf( return 0; }
Comments NOTHING