【做题记录】[NOI2008] 假面舞会—有向图上的环与最长链
生活随笔
收集整理的這篇文章主要介紹了
【做题记录】[NOI2008] 假面舞会—有向图上的环与最长链
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
luogu 1477 [NOI2008] 假面舞會
容易發(fā)現(xiàn):
-
如果圖中沒有環(huán),那么面具種數(shù)一定是所有聯(lián)通塊內(nèi)最長鏈之和,最少為 \(3\) 。
-
如果有環(huán),則面具種數(shù)一定是所有環(huán)的大小的最大公約數(shù)。
那么只要求出每一個聯(lián)通塊內(nèi)的最長鏈與環(huán)即可。
由于是有向邊,難以通過有向邊判斷聯(lián)通塊,因此考慮建立一個反向邊。將原來的邊邊權(quán)設為 \(1\) ,反向邊邊權(quán)設為 \(-1\) 。
在 \(\text{dfs}\) 時記錄這個聯(lián)通塊內(nèi)最大、最小的 \(dep\) ,相減即為最長鏈。而如果遇到了已經(jīng)訪問過的點,那么一定有環(huán)。
#include<bits/stdc++.h> using namespace std; #define infll 0x7f7f7f7f7f7f7f7fll #define inf 0x3f3f3f3f #define Maxn 100005 #define Maxm 1000005 typedef long long ll; inline int rd() {int x=0;char ch,t=0;while(!isdigit(ch = getchar())) t|=ch=='-';while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();return x=t?-x:x; } int gcd(int x,int y){ return (y==0)?x:gcd(y,x%y); } int n,m,tot,ans1,ans2,maxx,minn; int dfn[Maxn],hea[Maxn],nex[Maxm<<1],ver[Maxm<<1],edg[Maxm<<1]; bool vis[Maxn]; void add(int x,int y,int d){ ver[++tot]=y,nex[tot]=hea[x],hea[x]=tot,edg[tot]=d; } void dfs(int x,int Dep) {if(vis[x]) { ans1=gcd(ans1,abs(Dep-dfn[x])); return; }dfn[x]=Dep,vis[x]=true;maxx=max(maxx,dfn[x]),minn=min(minn,dfn[x]);for(int i=hea[x];i;i=nex[i]) dfs(ver[i],Dep+edg[i]); } int main() {n=rd(),m=rd();for(int i=1,x,y;i<=m;i++) x=rd(),y=rd(),add(x,y,1),add(y,x,-1);for(int i=1;i<=n;i++) if(!vis[i])maxx=-inf,minn=inf,dfs(i,0),ans2+=maxx-minn+1;if(ans1){if(ans1<3) printf("-1 -1\n");else{for(int i=3;i<=ans1;i++)if(ans1%i==0) { printf("%d %d\n",ans1,i); break; }}}else{if(ans2<3) printf("-1 -1\n");else printf("%d 3\n",ans2);}return 0; }總結(jié)
以上是生活随笔為你收集整理的【做题记录】[NOI2008] 假面舞会—有向图上的环与最长链的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 古汉语中表示死亡的字
- 下一篇: 【做题记录】[NOIP2016 普及组]