題目:傳送門
分析:這道題涉及的知識太多了。。要徹底喫透可能還需要幾天。分享一篇題解。ps:是時候看看算法書了。
代碼:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;
class POJ{
public:
POJ(int _n,int _m):n(_n),m(_m){
input();
initia();
buildG();
solve();
}
struct Edge{
int v;
int next;
};
void input();
void initia();
void solve();
void buildG();
void Tarjan(int,int);
void addEdge(int,int);
bool isBinaryG(int,int);
~POJ(){
int ans=0;
for(int i=1;i<=n;++i){
if(!canSettl[i]) ++ans;
}
cout<<ans<<endl;
delete[] vis;
delete[] hate;
delete[] dfn;
delete[] flag;
delete[] color;
delete[] low;
delete[] edges;
delete[] head;
delete[] canSettl;
}
private:
int n,m;
stack<int> s;
bool* vis;
bool** hate;
int* dfn;
bool* flag;
int* low;
int* color;
int* head;
Edge* edges;
bool* canSettl;
int cnt;
int time;
vector<int> connG;
};
void POJ::input(){
int N=n+1;
hate=new bool*[N];
for(int i=1;i<N;++i){
hate[i]=new bool[N];
memset(hate[i],false,sizeof(bool)*N);
}
int a,b;
while(m--){
scanf("%d %d",&a,&b);
hate[a][b]=true;
hate[b][a]=true;
}
}
void POJ::initia(){
int N=n+1;
int MAXE=2e6+5;
dfn=new int[N];
low=new int[N];
flag=new bool[N];
head=new int[N];
vis=new bool[N];
edges=new Edge[MAXE];
color=new int[N];
canSettl=new bool[N];
memset(canSettl,false,sizeof(bool)*N);
memset(vis,false,sizeof(bool)*N);
memset(dfn,0,sizeof(int)*N);
memset(low,0,sizeof(int)*N);
memset(head,-1,sizeof(int)*N);
cnt=0;
time=1;
}
void POJ::addEdge(int u,int v){
edges[cnt].v=v;
edges[cnt].next=head[u];
head[u]=cnt++;
}
void POJ::buildG(){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(!hate[i][j]&&i!=j){
addEdge(i,j);
}
}
}
}
void POJ::solve(){
for(int i=1;i<=n;++i){
if(!vis[i]){
Tarjan(i,0);
}
}
}
void POJ::Tarjan(int u,int fa){
dfn[u]=low[u]=time++;
s.push(u);
vis[u]=true;
for(int i=head[u];i!=-1;i=edges[i].next){
int v=edges[i].v;
if(v==fa) continue;
if(!vis[v]){
Tarjan(v,u);
low[u]=min(low[u],low[v]);
if(dfn[u]<=low[v]){
memset(flag,false,sizeof(bool)*(n+1));
memset(color,-1,sizeof(int)*(n+1));
connG.clear();
connG.push_back(u);
int temp;
do{
temp=s.top();
connG.push_back(temp);
flag[temp]=true;
s.pop();
}while(temp!=v);
flag[u]=true;
if(!isBinaryG(u,0)){
int vertN=connG.size();
for(int i=0;i<vertN;++i){
canSettl[connG[i]]=true;
}
}
}
}
else low[u]=min(low[u],dfn[v]);
}
}
bool POJ::isBinaryG(int u,int c){
color[u]=c;
for(int i=head[u];i!=-1;i=edges[i].next){
int v=edges[i].v;
if(!flag[v]) continue;
if(color[v]==-1){
if(!isBinaryG(v,c^1)) return false;
}
else if(color[u]==color[v]) return false;
}
return true;
}
int main(){
int n,m;
while(cin>>n>>m,n||m){
POJ _2942(n,m);
}
return 0;
}