山东理工月赛 D题

来源:互联网 发布:akb48少女时代知乎 编辑:程序博客网 时间:2024/05/01 07:24
题目大意]
  • 给定一张图,求最少加入几条边可以使得整个图成为一个边双连通图。
  • 具体的说也是非常简单:求双联通分量,染色,缩点,然后求度为1的点数,答案就是(这个数+1) Div 2。
  • 其他的就比较简单了,按照Low和Dfn的定义,如果某个点拓展完后Low=Dfn,那么栈中从栈顶到这个店为止的部分都属于同一个双联通分量。这个由Dfs树的性质决定的。这样求出来之后,只需要对这些点进行染色,不需要真的缩点,只要再去重新枚举原图中的边,向新的颜色不同的顶点之间加边即可。又由于双联通分量的定义,这样新的图一定是一个树,如果不是一个树,那有环的部分按照定义是应该在同一个双联通分量中的。然后求求度数,计算输出即可。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define maxn 5005#define maxm 40005struct Edge{    int v, next;} edge[maxm];int n, m;int head[maxn];int ecount, tcount;int dfn[maxn], vis[maxn], low[maxn], ans1,degree[maxn],vis1[maxn];void addedge(int a, int b){    edge[ecount].v = b;    edge[ecount].next = head[a];    head[a] = ecount;    //hash[a][b] = hash[b][a] = true;    ecount++;}void input(){    memset(head, -1, sizeof(head));    memset(vis1,0,sizeof(vis1));    ecount = 0;    int i,j;    ans1=0;    scanf("%d%d", &n, &m);    for (i = 0; i < m; i++)    {        int a, b;        scanf("%d%d", &a, &b);        a--;        b--;        vis[a]=vis[b]=1;        addedge(a, b);        addedge(b, a);    }    for(i=0;i<n;i++)    {    if(!vis[i])    {      ans1++;    }    }}void dfs(int fa, int u){    vis[u] = true;    low[u] = dfn[u] = tcount++;    for (int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].v;        if (v == fa)            continue;        if (!vis[v])            dfs(u, v);        low[u] = min(low[u], low[v]);    }}int tarjan(){    memset(dfn, 0, sizeof(dfn));    memset(vis, 0, sizeof(vis));    memset(degree, 0, sizeof(degree));    tcount = 0;    dfs(0, 0);    int ret = 0;    for (int i = 0; i < n; i++)        for (int j = head[i]; j != -1; j = edge[j].next)        {            int v = edge[j].v;            if (low[i] != low[v])                degree[low[i]]++;        }    for (int i = 0; i < n; i++)        if (degree[i] == 1)            ret++;    ret=(ret+1)/2;    if(ret)ret+=ans1;    else ret=ans1+(ans1?1:0);    return ret;}int main(){    //freopen("t.txt", "r", stdin);    int t;    cin>>t;    while(t--)    {   input();   int ans=0;     ans = tarjan();     printf("%d\n", ans);    }    return 0;}


 

原创粉丝点击