BZOJ1116: [POI2008]CLO

題目大意:給一張沒有重邊的無向圖,要求給其中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();
	}
}

發佈了170 篇原創文章 · 獲贊 42 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章