[HDU6403]: Card Game (dfs + DP + tree ring)

Topic Portal


Title Description

She is still in place I do not know I do not know.
Spread out some cards on the table, this is a game she usually very playful. Now cards still, she is not with me. Unconsciously, I opened the card, was recalled to play cards during that time.
Each card's front and back both have a number, every time I put the cards as I want on the table, and some of which she sucked the cards flipped, and finally makes up all of the numbers on the desktop They are different.
I looked at myself unwittingly opened the card, suddenly remembered more than once before she let me help her calculate the minimum required to achieve the target number of flip the least, and a minimum number of flip program to achieve their goals.
(Two methods are considered the same if and only if the same set of two ways need to flip the card)
if I put the solution process written procedures sent to her, she later time to play this game will be more liking of some?


Input Format

Each test point multiple sets of test data.
The first line has a positive integer and T represents the number of data sets.
Next, for each set of data, the first row there is a positive integer n, the number of cards on the table of FIG.
Then there are n lines of two integers x, y, both sides are represented by an x, y of the card, and the current number of upwardly x.


Output Format

For each test, a line output two integers, representing the minimum number of inversion, program number (program number of modulo 998,244,353).
If no solution is "-1 -1."


Sample

Sample input

3
4
1 2
1 3
4 5
4 6
2
1 1
1 1
3
1 2
3 4
5 6

Sample Output

2 4
-1 -1
0 1


Data range and tips

For 20% of the data:

$n \leqslant 20$

$T=1$

To 100% of the data:

$n \leqslant {10}^5$

$T \leqslant 50$

$1 \leqslant x,y \leqslant 2n$


answer

See this question, you must think of a solution using a mathematical method, then you're cold.

So to consider, the digital front to the back of the card even digital side, flip each card is equivalent to the reverse side, and our aim is to make out of all the points in each Unicom block diagram of a maximum of 1 .

But this time, it is divided into three cases:

  FIG. 1. If there are a number of edges within the block is greater than the number of points Unicom, then obviously did not meet, directly outputs "-1 -1" button.

  2. If the figures there is a link block within the number of edges is equal to the number of points, then the block is a ring Unicom tree, then we run clockwise and counterclockwise, respectively, this fast Unicom, see the need to reverse the direction to become smaller number If the answer in both directions the same, the program number is 2, and 1 otherwise.

  Figure 3. If there are a number of edges in the block equal points -1 Unicom, China Unicom is this block is a tree, then you consider using statistical DP answer, but obviously we need all the points for the tree root run again, violence run, then the time complexity is obviously very high; however, we found that for every change affects only the root even between it and its parent side would answer, but wisdom is +1 on an answer, or - 1, so that we can calculate the answer in the range of time allowed.


Code time

#include<bits/stdc++.h>
using namespace std;
struct rec
{
	int nxt;
	int to;
	bool w;//边权为1表示从正面连向反面
}e[200002];
int n;
int head[200001],cnt;
int b,d;
bool vis[200001];
int st,ed,po;
int sta[200001],top;
long long dp[200001],flag[200001];
long long ans,sum,num;
void pre_work()//多测不清空,爆零两行泪TAT……
{
	ans=0;
	sum=cnt=1;
	memset(head,0,sizeof(head));
	memset(vis,0,sizeof(vis));
	memset(dp,0,sizeof(dp));
	memset(flag,0,sizeof(flag));
}
void add(int x,int y,int w)//建边
{
	e[++cnt].nxt=head[x];
	e[cnt].to=y;
	e[cnt].w=w;
	head[x]=cnt;
}
void pre_dfs(int x)//跑每一个联通块,计算点数和边数
{
	d++;
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
	{
		b++;
		if(!vis[e[i].to])
			pre_dfs(e[i].to);
	}
}
void dfs(int x,int fa)//DP前对每一个联通块进行预处理
{
	flag[x]=0;
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
	{
		if(e[i].to==fa)continue;
		if(!vis[e[i].to])
		{
			dfs(e[i].to,x);
			flag[x]+=flag[e[i].to]+e[i].w;
		}
		else
		{
			st=x;
			ed=e[i].to;
			po=i;
		}
	}
}
void pro_dfs(int x,int fa)//DP统计答案
{
	sta[++top]=dp[x];
	for(int i=head[x];i;i=e[i].nxt)
		if(e[i].to!=fa&&i!=po&&i!=(po^1))
		{
			dp[e[i].to]=dp[x]+(e[i].w?-1:1);//换根之后的+1或者-1
			pro_dfs(e[i].to,x);
		}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		pre_work();
		for(int i=1;i<=n;i++)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			add(x,y,1);
			add(y,x,0);
		}
		for(int i=1;i<=2*n;i++)
			if(!vis[i])
			{
				b=d=0;
				pre_dfs(i);
				if(b/2>d)//判断是否有解
				{
					puts("-1 -1");
					goto nxt;//直接跳到结尾,和continue功能类似,但是可以指定跳转位置
				}
			}
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=2*n;i++)
		{
			if(!vis[i])
			{
				st=ed=po=top=0;
				num=1;
				dfs(i,0);
				dp[i]=flag[i];
				pro_dfs(i,0);
				if(!st)//如果是一棵树
				{
					sort(sta+1,sta+top+1);
					for(int j=2;j<=top;j++)
					{
						if(sta[j]!=sta[1])break;
						num++;
					}
					ans+=sta[1];
				}
				else//是一棵基环树
				{
					PO% = 2; 
					IF (DP [ST] + PO == DP [ED] + (PO ^. 1)) NUM = 2; 
					the else NUM =. 1; 
					ANS + = min (DP [ST] + PO, DP [ED] + (^ PO. 1)); 
				} 
				SUM = SUM NUM% 998 244 353 *; 
			} 
		} 
		the printf ( "% LLD LLD% \ n-", ANS, SUM); 
		NXT:; // the above "goto nxt;" jump to position 
	} 
	return 0; 
}

rp ++

Guess you like

Origin www.cnblogs.com/wzc521/p/11222273.html