题目大意:给一张没有重边的无向图,要求给其中N条边指定方向,使得每个点入度=1
(POI官网要求输出一组解,但是估计BZOJ当时懒得写SPJ了)
首先大概画一画能想到一个事情:
若每个点度数至少为2,则图一定有解
若有一个点度数为0,则该图一定无解
所以我们只需要处理一下度数为1的点,这些点连出的边必然指向自己
所以我们可以把这些点和这些边删掉,然后判断子图能否成立,这两个问题是等价的
至于这一步怎么做....我用两个priority_queue当做一个堆,然后维护度数...
这样子就过了,但是我1000ms+,别人都400ms左右QAQ
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define N 100010
using namespace std;
vector<int>V[N];
struct ppp{int num,v;};
bool operator >(const ppp &x,const ppp &y)
{
if(x.v!=y.v) return x.v>y.v;
return x.num>y.num;
}
bool operator ==(const ppp &x,const ppp &y)
{
return x.num==y.num&&x.v==y.v;
}
priority_queue<ppp,vector<ppp>,greater<ppp> >p,q;
bool del[N];
int du[N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int i,j,x,y;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
du[x]++;du[y]++;
V[x].push_back(y);
V[y].push_back(x);
}
for(i=1;i<=n;i++)
p.push((ppp){i,du[i]});
ppp tmp;
while(1)
{
tmp=p.top();
if(tmp.v==0) {puts("NIE");return 0;}
if(tmp.v>1) {puts("TAK");return 0;}
p.pop();
for(i=0;i<V[tmp.num].size();i++)
if(!del[V[tmp.num][i]])
{
q.push((ppp){V[tmp.num][i],du[V[tmp.num][i]]});
du[V[tmp.num][i]]--;
p.push((ppp){V[tmp.num][i],du[V[tmp.num][i]]});
}
del[tmp.num]=true;
while(p.top()==q.top()) p.pop(),q.pop();
}
}