UVA1361 Cactus

題目鏈接:

UVA
洛谷

題目大意:

仙人掌(Cactus)被定義爲每條邊(紫薯上此處寫成 每個點,巨坑)最多在一個簡單迴路上的連通無向圖。(簡單迴路指結點不重複經過的環)。
Cactus
給定一個無向圖,求它有多少生成子圖(包括自身)是仙人掌。如果原圖不是仙人掌,輸出0。

題解:

子圖:原圖的一部分。
生成子圖:包含原圖所有點的子圖。
相當於拆去原圖的一些邊,使得圖仍然是一個仙人掌。
在原圖爲仙人掌的前提下,拆去的邊一定是環上的邊,切一個環最多拆一條邊,所以單獨考慮一個環能拆的方案數爲環的邊數加一。因爲是仙人掌,每個環不共邊,所以每個環拆邊是獨立的,整個圖的方案數爲所有環的方案數的乘積。
仙人掌上每個環構成一個雙連通分量,且連通分量內點數等於邊數。所以可以通過求雙連通分量,再判斷是否每一個雙連通分量內的點數均等於邊數,來判斷無向圖是否是一個仙人掌。
注意只有兩個點的連通分量不在考慮範圍內。
如果是仙人掌,最終答案爲大於2的連通分量的大小加一的乘積,否則爲0。
*最終的結果可能非常大,最大的達到了六千多爲數(天坑)。。。

代碼:

#include <bits/stdc++.h>
#define LL long long
#define LD long double
#define ULL unsigned long long
#define UI unsigned int
#define PII pair<int,int>
#define MPII(x,y) pair<int,int>{x,y}
#define _for(i,j,k) for(int i=j;i<=k;i++)
#define for_(i,j,k) for(int i=j;i>=k;i--)
#define efor(i,u) for(int i=head[u];i;i=net[i])
#define lowbit(x) (x&-x)
#define ls(x) x<<1
#define rs(x) x<<1|1
#define inf 0x3fffffff
//#pragma comment(linker, "/STACK:10240000000,10240000000")
using namespace std;
const int maxn = 6e6 + 5;
const int M = 1e9 + 7;
inline int mad(int a,int b){return (a+=b)>=M?a-M:a;}
//大數模板
#define MAXN 9999
#define MAXSIZE 1010
#define DLEN 4
class BigNum {
	private:
		int a[7000];  //位數可變
		int len;
	public:
		BigNum() {
			len=1;
			memset(a,0,sizeof(a));
		}
		BigNum(const int);   
		BigNum(const char*); 
		BigNum(const BigNum &); 
		BigNum &operator=(const BigNum &); 
		friend istream& operator>>(istream&,BigNum&); 
		friend ostream& operator<<(ostream&,BigNum&); 

		BigNum operator+(const BigNum &)const; 
		BigNum operator-(const BigNum &)const;
		BigNum operator*(const BigNum &)const;
		BigNum operator/(const int &)const;
		
		BigNum operator^(const int &)const; 
		int operator%(const int &)const; 
		bool operator>(const BigNum &T)const; 
		bool operator>(const int &t)const; 

		void print(); 
};
BigNum::BigNum(const int b) {
	int c,d=b;
	len=0;
	memset(a,0,sizeof(a));
	while(d>MAXN) {
		c=d-(d/(MAXN+1))*(MAXN+1);
		d=d/(MAXN+1);
		a[len++]=c;
	}
	a[len++]=d;
}
BigNum::BigNum(const char *s) {
	int t,k,index,L,i;
	memset(a,0,sizeof(a));
	L=strlen(s);
	len=L/DLEN;
	if(L%DLEN)len++;
	index=0;
	for(i=L-1; i>=0; i-=DLEN) {
		t=0;
		k=i-DLEN+1;
		if(k<0)k=0;
		for(int j=k; j<=i; j++)
			t=t*10+s[j]-'0';
		a[index++]=t;
	}
}
BigNum::BigNum(const BigNum &T):len(T.len) {
	int i;
	memset(a,0,sizeof(a));
	for(i=0; i<len; i++)
		a[i]=T.a[i];
}
BigNum& BigNum::operator=(const BigNum &n) {
	int i;
	len=n.len;
	memset(a,0,sizeof(a));
	for(i=0; i<len; i++)         a[i]=n.a[i];
	return *this;
}
istream& operator>>(istream &in,BigNum &b) {
	char ch[MAXSIZE*4];
	int i=-1;
	in>>ch;
	int L=strlen(ch);
	int count=0,sum=0;
	for(i=L-1; i>=0;)     {
		sum=0;
		int t=1;
		for(int j=0; j<4&&i>=0; j++,i--,t*=10)         {
			sum+=(ch[i]-'0')*t;
		}
		b.a[count]=sum;
		count++;
	}
	b.len=count++;
	return in;
}
ostream& operator<<(ostream& out,BigNum& b) {
	int i;
	cout<<b.a[b.len-1];
	for(i=b.len-2; i>=0; i--) {
		printf("%04d",b.a[i]);
	}
	return out;
}
BigNum BigNum::operator+(const BigNum &T)const { 
	BigNum t(*this);
	int i,big;
	big=T.len>len?T.len:len;
	for(i=0; i<big; i++) {
		t.a[i]+=T.a[i];
		if(t.a[i]>MAXN)         {
			t.a[i+1]++;
			t.a[i]-=MAXN+1;
		}
	}
	if(t.a[big]!=0)        t.len=big+1;
	else t.len=big;
	return t;
}
BigNum BigNum::operator-(const BigNum &T)const {
	int i,j,big;
	bool flag;
	BigNum t1,t2;
	if(*this>T) {
		t1=*this;
		t2=T;
		flag=0;
	} else     {
		t1=T;
		t2=*this;
		flag=1;
	}
	big=t1.len;
	for(i=0; i<big; i++)     {
		if(t1.a[i]<t2.a[i])         {
			j=i+1;
			while(t1.a[j]==0)                 j++;
			t1.a[j--]--;
			while(j>i)                 t1.a[j--]+=MAXN;
			t1.a[i]+=MAXN+1-t2.a[i];
		}         else t1.a[i]-=t2.a[i];
	}
	t1.len=big;
	while(t1.a[len-1]==0 && t1.len>1)     {
		t1.len--;
		big--;
	}
	if(flag)         t1.a[big-1]=0-t1.a[big-1];
	return t1;
}
BigNum BigNum::operator*(const BigNum &T)const {
	BigNum ret;
	int i,j,up;
	int temp,temp1;
	for(i=0; i<len; i++) {
		up=0;
		for(j=0; j<T.len; j++) {
			temp=a[i]*T.a[j]+ret.a[i+j]+up;
			if(temp>MAXN) {
				temp1=temp-temp/(MAXN+1)*(MAXN+1);
				up=temp/(MAXN+1);
				ret.a[i+j]=temp1;
			}             else             {
				up=0;
				ret.a[i+j]=temp;
			}
		}
		if(up!=0)            ret.a[i+j]=up;
	}
	ret.len=i+j;
	while(ret.a[ret.len-1]==0 && ret.len>1)ret.len--;
	return ret;
}
BigNum BigNum::operator/(const int &b)const { 
	BigNum ret;
	int i,down=0;
	for(i=len-1; i>=0; i--) {
		ret.a[i]=(a[i]+down*(MAXN+1))/b;
		down=a[i]+down*(MAXN+1)-ret.a[i]*b;
	}
	ret.len=len;
	while(ret.a[ret.len-1]==0 && ret.len>1)         ret.len--;
	return ret;
}
int BigNum::operator%(const int &b)const { 
	int i,d=0;
	for(i=len-1; i>=0; i--)        
		d=(((long long)d*(MAXN+1))%b+a[i])%b;
	return d;
}
BigNum BigNum::operator^(const int &n)const { 
	BigNum t,ret(1);
	int i;
	if(n<0)exit(-1);
	if(n==0)return 1;
	if(n==1)return *this;
	int m=n;
	while(m>1) {
		t=*this;
		for(i=1; (i<<1)<=m; i<<=1)            t=t*t;
		m-=i;
		ret=ret*t;
		if(m==1)ret=ret*(*this);
	}
	return ret;
}
bool BigNum::operator>(const BigNum &T)const { 
	int ln;
	if(len>T.len)return true;
	else if(len==T.len) {
		ln=len-1;
		while(a[ln]==T.a[ln]&&ln>=0)           ln--;
		if(ln>=0 && a[ln]>T.a[ln])            return true;
		else            return false;
	} else
		return false;
}
bool BigNum::operator>(const int &t)const {
	BigNum b(t);
	return *this>b;
}
void BigNum::print() { 
	int i;
	printf("%d",a[len-1]);
	for(i=len-2; i>=0; i--)
		printf("%04d",a[i]);
	printf("\n");
}
BigNum bm;
int head[maxn],net[maxn],e[maxn],cnt,n,m;
bool flag;
LL an;
void add(int u,int v){
	e[++cnt]=v;
	net[cnt]=head[u];
	head[u]=cnt;
}
//BCC
int df,dfn[maxn],low[maxn],bccn[maxn],bc;
int isc[maxn];//割點
vector<int> bcc[maxn];
stack<int> st;
void tarjan(int u,int pre){
	dfn[u]=low[u]= ++df;
	int child=0;
	st.push(u);
	for(int i=head[u];i;i=net[i]){
		if(!dfn[e[i]]){
			child++;
			tarjan(e[i],u);
			low[u]=min(low[u],low[e[i]]);
			if(low[e[i]]>=dfn[u]){
				isc[u]=1;
				bc++;bcc[bc].clear();
				bcc[bc].push_back(u);bccn[u]=bc;
				while(bccn[e[i]]!=bc){
					bcc[bc].push_back(st.top());
					bccn[st.top()]=bc;
					st.pop();
				}
				if(bcc[bc].size()>2){
					int ct=0;
					for(auto x:bcc[bc]){
						for(int j=head[x];j;j=net[j]){
							if(bccn[e[j]]==bc){
								ct++;
							}
						}
					}
					//cout<<ct<<" "<<bcc[bc].size()<<endl;
					if(ct!=2*bcc[bc].size()) flag=false;
					//an = (LL)an*(ct/2+1ll);
					if(flag){
						bm = bm*(ct/2+1);
					}
				}
			}
		}
		else if(dfn[e[i]]<dfn[u]&&e[i]!=pre){
			low[u]=min(low[u],dfn[e[i]]);
		}
	}
	if(pre==0&&child==1) isc[u]=0;
} 
int find_bcc(){
	int ret=0;
	df=bc=0;
	for(int i=1;i<=n;++i) dfn[i]=low[i]=isc[i]=bccn[i]=0;
	for(int i=1;i<=n;++i) if(!dfn[i]){
		ret++;
		if(ret>1) break;
		while(!st.empty()) st.pop();
		tarjan(i,0);
	}
	return ret;
}
int main(){
	int fst=0;
	while(scanf("%d %d",&n,&m)==2){
		if(fst) cout<<"\n";
		else fst++;
		flag=true;an=1ll;bm=1;
		int k,u,v; 
		_for(i,1,m){
			scanf("%d %d",&k,&u);
			_for(j,2,k){
				scanf("%d",&v);
				add(u,v);
				add(v,u);
				u=v;
			}
		}
		int bcnt = find_bcc();
//		cout<<bcnt<<" "<<flag<<endl;
		if(bcnt!=1) flag=false;
		if(flag){
			cout<<bm<<"\n";
			//cout<<an<<"\n";
		}
		else{
			cout<<"0\n";
		}
		_for(i,1,n) head[i]=0;
		cnt=0;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章