LOJ洛谷P3225:矿场搭建(割点、点双)
生活随笔
收集整理的這篇文章主要介紹了
LOJ洛谷P3225:矿场搭建(割点、点双)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 解析
- 代碼
解析
我的實現不夠簡潔,導致bug越調越謎…
關鍵就是**找被割點分開的分量的方法:dfs!!!
一下子就豁然開朗了
代碼
#include<bits/stdc++.h> using namespace std; #define ll long long const int N=2e3+100; const double eps=1e-6; inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return f*x; } int n,m; int ans; struct node{int to,nxt,from; }p[N<<1]; int fi[N],cnt; inline void addline(int x,int y){//printf("%d->%d w=%d\n",x,y,w);p[++cnt]=(node){y,fi[x],x};fi[x]=cnt; } int dfn[N],low[N],zhan[N],tim,top,cut[N],r,tot; void tarjan(int x){dfn[x]=low[x]=++tim;zhan[++top]=x;int nm=0;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;//printf("x=%d to=%d\n",x,to);if(!dfn[to]){++nm;tarjan(to);if(low[to]>=dfn[x]){cut[x]=1;}low[x]=min(low[x],low[to]);}else low[x]=min(low[x],dfn[to]);}if(x==r) cut[x]=nm>1; } int num,Cut,tag[N],t; bool vis[N]; void dfs(int x){if(vis[x]||tag[x]==t) return;num++;//printf("x=%d\n",x);if(cut[x]){tag[x]=t;Cut++;return;}vis[x]=1;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;dfs(to);} } int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifint o=0;while(1){memset(fi,-1,sizeof(fi));cnt=-1;memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));tim=0;top=0;memset(cut,0,sizeof(cut));memset(tag,0,sizeof(tag));m=read();n=0;if(!m) return 0;for(int i=1;i<=m;i++){int x=read(),y=read();addline(x,y);addline(y,x);n=max(n,max(x,y));}tot=n;for(int i=1;i<=n;i++){r=i;if(!dfn[i]) tarjan(i);}ll nm=0,ans=1;for(int i=1;i<=n;i++){//printf("i=%d cut=%d\n",i,cut[i]);if(!vis[i]&&!cut[i]){num=0;Cut=0;t=i;dfs(i);printf("i=%d num=%d Cut=%d\n",i,num,Cut);if(Cut==0){nm+=2;ans*=num*(num-1)/2;}else if(Cut==1){nm++;ans*=(num-1);}}}printf("Case %d: %lld %lld\n",++o,nm,ans);} } /* 4 1 2 2 3 1 3 3 4 */總結
以上是生活随笔為你收集整理的LOJ洛谷P3225:矿场搭建(割点、点双)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LOJ:出纳员问题(差分约束)
- 下一篇: 准大一新生笔记本电脑怎么选大一新生如何选