您的位置:首页 > 其它

Gym 100712H(边双联通+树的直径)

2017-07-23 14:23 309 查看


题意:问给你一个无向图。你可以任意加一条边问加边之后最少的桥数是多少

做法:先缩点。缩完之后走一个树的dfs,求两个端点并且记录深度。

肯定把树的两端连起来的桥数最少吧。然后联通分量总数-树的直径deep就是答案了。

//china no.1
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;

#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x) memset(x,0,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1e3+10;
const int maxx=2e5+100;
const double EPS=1e-7;
const int MOD=10000007;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}

int vis[maxx],dfn[maxx],low[maxx],bel[maxx],num[maxx],res,pre[maxx],a[maxx],in[maxx];
int cont=1,n,m,num2[maxx],num3[maxx],ans[maxx],link[maxx];
struct node
{
int u,v,w;
}s[maxx];
vector<int>G[maxx],G_new[maxx];
queue<int>Q;
stack<int>S;
vector<node>g[maxx];
LL dis1[maxx],dis2[maxx];
LL max_len;int st,ed;
void tarjan(int fa,int x)
{
dfn[x]=low[x]=cont++;
S.push(x);
vis[x]=1;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(fa==nex) continue;
if(!vis[nex])
{
tarjan(x,nex);
low[x]=min(low[x],low[nex]);
}
else if(vis[nex]==1)
low[x]=min(low[x],dfn[nex]);
}
if(dfn[x]==low[x])
{
res++;
while(1)
{
int t=S.top();
S.pop();
bel[t]=res;
vis[t]=2;
// pre[res]=min(pre[res],t);
if(x==t)break;
}
}
}

void init()
{
me(pre);me(vis);(low);me(bel);me(dfn);me(num);me(in);
me(num);me(num2);me(num3);me(ans);me(link);
for(int i=1;i<=n;i++)
{
G[i].clear();
pre[i]=INF;
g[i].clear();
}
me(s);
// memset(a,INF,sizeof(a));
res=0;cont=1;
}

void dd(int u,int fa,LL len,int flag)
{
if(flag) dis1[u]=len;
if(!flag) dis2[u]=len;
if(flag&&len>max_len) st=u,max_len=len;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i].v;
if(v==fa) continue;
dd(v,u,len+g[u][i].w,flag);
}
}

int t;
//void solve()
int main()
{
cin>>t;
for(int cas=1;cas<=t;cas++)
{
// while(~scanf("%d%d",&n,&m))
// {
//close();
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++)
{
int x,y,z;
//scanf("%d%d%d",&x,&y,&z);
scanf("%d%d",&x,&y);
// x++;y++;
s[i].u=x;s[i].v=y;s[i].w=1;
G[x].push_back(y);
G[y].push_back(x);
}
tarjan(-1,1);
int ans=0;
for(int i=1;i<=m;i++)
{
int u=bel[s[i].u],v=bel[s[i].v];
LL w=s[i].w;
if(u!=v)
{
ans++;
g[u].push_back(node{0,v,w});
g[v].push_back(node{0,u,w});
}
}
me(dis1);me(dis2);
max_len=-1;
dd(1,-1,0,1);
ed=st;
max_len=-1;
dd(st,-1,0,1);
// swap(st,ed);
// dd(ed,-1,0,0);
cout<<ans-max_len<<endl;
// cout<<ans<<endl;
}
}
/*
int main()
{
int t;
//t=1;
// close();
cin>>t;
for(cas=1;cas<=t;cas++)
solve();
}*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: