【BZOJ1718】&&【POJ3177】Redundant Paths

1718: [Usaco2006 Jan] Redundant Paths 分離的路徑

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 452  Solved: 239
[Submit][Status][Discuss]

Description

In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the herd are forced to cross near the Tree of Rotten Apples. The cows are now tired of often being forced to take a particular path and want to build some new paths so that they will always have a choice of at least two separate routes between any pair of fields. They currently have at least one route between each pair of fields and want to have at least two. Of course, they can only travel on Official Paths when they move from one field to another. Given a description of the current set of R (F-1 <= R <= 10,000) paths that each connect exactly two different fields, determine the minimum number of new paths (each of which connects exactly two fields) that must be built so that there are at least two separate routes between any pair of fields. Routes are considered separate if they use none of the same paths, even if they visit the same intermediate field along the way. There might already be more than one paths between the same pair of fields, and you may also build a new path that connects the same fields as some other path.php

    爲了從F(1≤F≤5000)個草場中的一個走到另外一個,貝茜和她的同伴們有時不得不路過一些她們討厭的可怕的樹.奶牛們已經厭倦了被迫走某一條路,因此她們想建一些新路,使每一對草場之間都會至少有兩條相互分離的路徑,這樣她們就有多一些選擇.
    每對草場之間已經有至少一條路徑.給出全部R(F-1≤R≤10000)條雙向路的描述,每條路鏈接了兩個不一樣的草場,請計算最少的新建道路的數量, 路徑由若干道路首尾相連而成.兩條路徑相互分離,是指兩條路徑沒有一條重合的道路.可是,兩條分離的路徑上能夠有一些相同的草場. 對於同一對草場之間,可能已經有兩條不一樣的道路,你也能夠在它們之間再建一條道路,做爲另外一條不一樣的道路.

Input

* Line 1: Two space-separated integers: F and R * Lines 2..R+1: Each line contains two space-separated integers which are the fields at the endpoints of some path.ios

    第1行輸入F和R,接下來R行,每行輸入兩個整數,表示兩個草場,它們之間有一條道路.

 

Output

* Line 1: A single integer that is the number of new paths that must be built.ide

    最少的須要新建的道路數.

Sample Input

7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7

Sample Output

2

HINT

 

 

Source

Goldui

 
Sol:
我來詳細的說一下這道題
首先 咱們不難發現已是邊雙聯通份量的點集必定沒有用了,縮縮縮。
縮完以後 咱們發現咱們缺乏些什麼? 咱們缺乏要將整張圖縮成一個點 
那怎麼連最優?
假設咱們全都向根連,確定不優。
我也不知道怎麼yy的,反正度爲1的點之間互相連是最優解

 

 

(感謝caidongxiao大神的題解)spa

具體的證實……咱們考慮怎樣讓度數爲1的點之間互相連通就行了,確定是互相連,可是直接隨便連是有問題的,因此說應該讓LCA最遠的互相連一下,而後次遠的相連,我也不會證實,反正是個貪心。設縮點後葉節點的個數爲$leaf$個debug

答案就是$\lceil \frac{leaf}{2} \rceil$3d

邊雙聯通份量
挺好寫的 直接寫
1A 基本上就是普通的tarjan加個條件
/*To The End Of The Galaxy*/
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iomanip>
#include<bitset>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#define debug(x) cerr<<#x<<"="<<x<<endl
#define INF 0x7f7f7f7f
#define llINF 0x7fffffffffffll
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
inline int init()
{
    int now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
inline long long llinit()
{
    long long now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
struct edge
{
    int from,to,val,pre;
}Edge[20005];
int head[5005],instack[5005],dfs_time,dfn[5005],low[5005];
int eccnumber,bel[5005];
int du[5005];
stack<int> s;
int topt,n,m,cnt;
map<pii,int> mp;
inline void addedge(int from,int to,int val)
{
    ++cnt;
    Edge[cnt]=((edge){from,to,val,head[from]});
    head[from]=cnt;
}
void tarjan(int now,int fa)
{
    dfn[now]=low[now]=++dfs_time;
    s.push(now);instack[now]=1;
    for(int j=head[now];j;j=Edge[j].pre)
    {
        if(!dfn[Edge[j].to])
        {
            tarjan(Edge[j].to,now);
            low[now]=min(low[now],low[Edge[j].to]);
        }
        else if(instack[Edge[j].to]&&fa!=Edge[j].to)
        {
            low[now]=min(low[now],dfn[Edge[j].to]);
        }
    }
    if(dfn[now]==low[now])
    {
        ++eccnumber;
        while(1)
        {
            topt=s.top();s.pop();
            instack[topt]=false;
            bel[topt]=eccnumber;
            if(topt==now)break;
        }
    }
}
inline void rebuild()
{
    for(int i=1;i<=cnt;i+=2)
    {
        if(bel[Edge[i].from]!=bel[Edge[i].to]&&!mp[make_pair(bel[Edge[i].from],bel[Edge[i].to])])
        {
            mp[make_pair(bel[Edge[i].from],bel[Edge[i].to])]=1;
            du[bel[Edge[i].from]]++;du[bel[Edge[i].to]]++;
        }
    }
}
int main()
{
    int a,b;
    n=init();m=init();
    for(int i=1;i<=m;i++)
    {
        a=init();b=init();
        addedge(a,b,1);
        addedge(b,a,1);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        {
            tarjan(i,0);
        }
    }
    rebuild();
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(du[i]==1)
        {
            ans++;
        }
    }
    ans++;
    printf("%d\n",ans/2);
    return 0;
}
View Code
相關文章
相關標籤/搜索