HDU-6370

tarjan找环。我们通过枚举一个点的入边为wolf/village出边为wolf/village ,可以知道,当且仅当,一个环里面有且仅有一个出边为wolf的时候,被指向的那个人为wolf。
一旦能够确定wolf了,那么所有指向wolf的人,如果出边为village,那么这个人也是wolf。反向dfs即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	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;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1e5 + 10;
struct eg{
	int v, wi, next;
}out[N], in[N];
int head_out[N], head_in[N];
struct tt {
	int u, v, wi;
};
stack<int>st;
int dfn[N], low[N];
eg to[N];
int vis[N];
int now, ans;
int cnt1, cnt2;
int scc_cnt = 0;
vector<int>block[N];
void addedge(int u, int v, int wi)
{
	out[cnt1].v = v;
	out[cnt1].wi = wi;
	out[cnt1].next = head_out[u];
	to[u] = eg{ v,wi };
	head_out[u] = cnt1++;
	in[cnt2].v = u;
	in[cnt2].wi = wi;
	in[cnt2].next = head_in[v];
	head_in[v] = cnt2++;
}
int tot;
void tarjan(int u)
{
	dfn[u] = low[u] = ++tot;
	vis[u] = 1;
	st.push(u);
	int v = to[u].v;
	int temp_w = to[u].wi;
		if (!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(vis[v])	
		{
			low[u] = min(low[u],dfn[v]);
		}
//	vis[u] = 0;
	if (dfn[u] == low[u])
	{
		scc_cnt++;
		int cur;
		do
		{
			cur = st.top(); st.pop();
			vis[cur] = 0;
			block[scc_cnt].push_back(cur);
		} while (cur!= u);
	}
}
void dfs(int u)
{
	for (int i=head_in[u];~i;i=in[i].next)
	{
		int v = in[i].v;
		int temp_wi = in[i].wi;
		if (temp_wi == 0)
		{
			ans++;
			dfs(v);
		}
	}
}
int n, T;
int main()
{
	T = read();
	while (T--)
	{
		n = read();
		upd(i, 0, n)low[i] = dfn[i] = 0;
		tot = 0;
		cnt1 = cnt2 = 0; scc_cnt = 0;
		while(!st.empty())st.pop();
		memset(head_out, -1, sizeof(head_out));
		memset(head_in, -1, sizeof(head_in));
		ans = 0;
		char s[10];
		int v, w;
		upd(i, 1, n)
		{
			v = read(); scanf("%s", s);
			if(s[0]=='w')
			addedge(i, v, 1);
			else addedge(i, v, 0);
		}
		upd(i, 1, n)
		{
			if (!dfn[i])
			{
				tarjan(i);
			}
		}
		upd(i, 1, scc_cnt)
		{
			if (block[i].size() == 1)continue;
			int temp_num = 0;
			for (auto tp : block[i])
			{
				int v = to[tp].v;
				int w = to[tp].wi;
				if (w == 1) { temp_num++; now = v; }
			}
			if (temp_num == 1)
			{
				ans++;
				dfs(now);
			}
		}
		upd(i, 0, scc_cnt)block[i].clear();
		printf("%d %d\n", 0, ans);
	}
}

猜你喜欢

转载自www.cnblogs.com/LORDXX/p/12550843.html
今日推荐