hdu6403(基环树+dfs+DP)

10 篇文章 0 订阅

首先图得建得出来才有后话(反正窝是建不出来

图是这样建的。。从反面数字向正面数字连边,然后题目转化成反向最少的边使所有点的入度不大于1

然后就要讨论一下了。。根据容斥原理,对一个连通块如果边数大于点数那么必定有点是入度大于1的。。所以每个连通块只能是树或者基环树。。

树的话可以根据容斥原理得到有一个点的入度是0的,所以可以枚举这个入度为0的点,转成有根数,根据有根树的方向将边反向即可。。实现的时候先算一个点然后用这个点的反转边数来推到另一个边的反转边数,可以说是DP吧。。。2遍dfs就求出来了。。

然后对基环树的情况,首先外向树的边已经定向,一遍dfs找出反转边数。。然后讨论一下环上顺时针和逆时针的反转情况,取最小或者都取。。

就是分类讨论写起来烦了一点。。难度其实不大。。

然后被无向图2点环坑了好久。。以后写基环树的时候一两点的情况得考虑清楚。。

 

 

/**
 *          ┏┓    ┏┓
 *          ┏┛┗━━━━━━━┛┗━━━┓
 *          ┃       ┃  
 *          ┃   ━    ┃
 *          ┃ >   < ┃
 *          ┃       ┃
 *          ┃... ⌒ ...  ┃
 *          ┃              ┃
 *          ┗━┓          ┏━┛
 *          ┃          ┃ Code is far away from bug with the animal protecting          
 *          ┃          ┃   神兽保佑,代码无bug
 *          ┃          ┃           
 *          ┃          ┃        
 *          ┃          ┃
 *          ┃          ┃           
 *          ┃          ┗━━━┓
 *          ┃              ┣┓
 *          ┃              ┏┛
 *          ┗┓┓┏━━━━━━━━┳┓┏┛
 *           ┃┫┫       ┃┫┫
 *           ┗┻┛       ┗┻┛
 */
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 200005
#define nm 400005 
#define N 1000005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const int inf=998244353;
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}



struct edge{int t;bool f,v;edge*next,*rev;}e[nm],*h[NM],*o=e;
void _add(int x,int y,bool v){o->t=y;o->v=v;o->next=h[x];h[x]=o++;}
void add(int x,int y){_add(x,y,1);_add(y,x,0);h[x]->rev=h[y];h[y]->rev=h[x];}
int n,_x,_y,c[NM],f[NM],tot,cnt,sz[NM],b[NM],ans1,_t,s;
bool v[NM];
ll ans2;

int find(int x){return f[x]==x?x:f[x]=find(f[x]);}

void dfs1(int x){
    link(x)if(f[x]!=j->t){
	f[j->t]=x;
	dfs1(j->t);
	if(!j->v)cnt++;
    }
}
void dfs2(int x){
    if(cnt<s)s=cnt,_t=1;else if(cnt==s)_t++;
    link(x)if(f[x]!=j->t){
	if(j->v)cnt++;else cnt--;
	dfs2(j->t);
	if(j->v)cnt--;else cnt++;
    }
}
void cir(int x){
    v[x]++;
    link(x)if(!j->f){
	j->f=j->rev->f=true;
	if(v[j->t]){_x=j->t;c[++tot]=x;break;}
	else cir(j->t);
	if(_x){c[++tot]=x;break;}
    }
    if(_x==x)_x=0;
}

int main(){
    //freopen("data.in","r",stdin);
    int _=read();while(_--){
	mem(e);mem(h);o=e;mem(sz);mem(b);mem(v);
	n=read();ans1=0;ans2=1;
	inc(i,1,2*n)f[i]=i;
	inc(i,1,n){
	    _x=read();_y=read();add(_y,_x);
	    b[_x]++;b[_y]++;
	    int x=find(_x),y=find(_y);
	    if(x==y)continue;
	    f[x]=y;
	}
	inc(i,1,2*n)if(find(i)!=i)b[f[i]]+=b[i],sz[f[i]]++;
	inc(i,1,2*n)if(f[i]==i){
	    sz[i]++;s=inf;cnt=0;_t=0;
	    if(b[i]/2==sz[i]-1){
		dfs1(i);
		dfs2(i);
	    }else if(b[i]/2==sz[i]){
		cnt=tot=_x=0;cir(i);c[tot+1]=c[1];c[0]=c[tot];
		inc(k,1,tot)link(c[k])if(j->t==c[k+1]&&j->v){cnt++;break;}
		cnt=min(cnt,tot-cnt);_t=1;if(cnt*2==tot)_t=2;
		inc(k,1,tot)link(c[k])if(j->t!=c[k-1]&&j->t!=c[k+1]){f[j->t]=c[k];dfs1(j->t);if(!j->v)cnt++;}
		s=cnt;
	    }
	    if(s<inf)ans2*=_t,ans1+=s,ans2%=inf;else {ans1=ans2=-1;break;}
	}
	printf("%d %lld\n",ans1,ans2);
    }
    return 0;
}

 

 

2018百度之星复赛晋级名单出炉(增加20%晋级名额)~

Card Game

Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 109    Accepted Submission(s): 29


 

Problem Description

Alice and Bob are playing a card game. In this card game, a number is written on each face of the playing card. The rule of the game is described as follows:

- Alice arranges the cards in a row, and for each of the cards, she chooses one of its faces to place it up;
- Bob turns over minimum number of cards to make all numbers on the front faces unique.

They play the game some times, and Bob always succeeds making the numbers unique. However, both of them are not sure whether the number of cards flipped is minimum. Moreover, they want to figure out the number of different ways of turning over minimum number of cards to make the numbers unique. Two ways are considered equal if and only if the sets of flipped cards are equal. Please write a program to help them!

 

 

Input

The first line of the input is a single integer T (1≤T≤50), the number of test cases.

Each test case begins with a single line of integer n (1≤n≤105), the number of cards on the table. Then follow n lines, specifying the cards that Alice arranges. Each of these n lines contains two integers x,y (1≤x,y≤2n), meaning that Alice places a card with number x on the front face and number y on the back face.

It is guaranteed that the sum of n over all test cases does not exceed 106.

 

 

Output

For each test case, display two integers in a line, the minimum number of cards to turn over, and the number of different ways of flipping modulo 998244353, respectively. If it is impossible to turn over cards to make all numbers unique, display -

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值