首先图得建得出来才有后话(反正窝是建不出来
图是这样建的。。从反面数字向正面数字连边,然后题目转化成反向最少的边使所有点的入度不大于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;
}
Card GameTime 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:
Input The first line of the input is a single integer T (1≤T≤50), the number of test cases.
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 - |