日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

最小點割集(點連通度)

系統(tǒng) 1810 0


????? 無向(有向)圖G中,給定源點s和終點t,至少要刪去多少個點(具體一點,刪哪些點),使得s和t不連通。這個問題就是 點連通度 ,也叫 最小點割集

???? 一般最小點割轉(zhuǎn)化到最小邊割上,將原圖中的點v拆成v'和v'',且w(v,v'')=1。對于原圖中的有向邊(u,v),則有w(u'',v')=INF;若是無向邊,則還要加上邊:w(v'',v')=INF。然后求以s''為源點,t'為匯點的最大流。 maxflow即為最少需要刪的點數(shù),割邊集對應(yīng)了具體刪的點的一組解

???? 值得 注意 的是最小點割的解有很多,如下圖:



?

最小點割集(點連通度)

?

???? 最小點割的方案有4種:(4,3),(4,1),(2,3),(2,1)。若按上述方法求解,最小割點集為(4,3)。

?

例: POJ1815

???? 題意: 給出一個圖,問要刪去多少個點,才能使得從1到不了n。顯然這是個最小點割問題。但題目又要求,如果有多種方案,輸出序號最小的一種。

???? 解: 顯然,如果s和t直接相連,則無解。求最小點割集方法并不難,取割邊集即可,關(guān)鍵是如何滿足題意"序號最小的一種"。有一種簡單的貪心:從2到n-1枚舉刪除每一個點,看刪除之后流量是否發(fā)生變化,若變化,則這點就算在解中;否則恢復這個點。過程一直進行到maxflow=0為止。

    #include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 0x7fffffff;
const int maxv = 410;
const int maxe = maxv*maxv*10;
int n;
int g[205][205];
struct Edge
{
    int v;
    int next;
    int flow;
};
Edge e[maxe];
int head[maxv],edgeNum;
int now[maxv],d[maxv],vh[maxv],pre[maxv],preh[maxv];
int result[maxv];
bool cut[maxv];

void addEdge(int a,int b,int c)
{
    e[edgeNum].v = b;
    e[edgeNum].flow = c;
    e[edgeNum].next = head[a];
    head[a] = edgeNum++;
    e[edgeNum].v = a;
    e[edgeNum].flow = 0;
    e[edgeNum].next = head[b];
    head[b] = edgeNum++;
}

void Init()
{
    edgeNum = 0;
    memset(head,-1,sizeof(head));
    memset(d,0,sizeof(d));
}

int sap(int s,int t,int n)       //源點,匯點,結(jié)點總數(shù)
{
    int i,x,y;
    int f,ans = 0;
    for(i = 0; i < n; i++)
        now[i] = head[i];
    vh[0] = n;
    x = s;
    while(d[s] < n)
    {
        for(i = now[x]; i != -1; i = e[i].next)
            if(e[i].flow > 0 && d[y=e[i].v] + 1 == d[x])
                break;
            if(i != -1)
            {
                now[x] = preh[y] = i;
                pre[y] = x;
                if((x=y) == t)
                {
                    for(f = INF,i=t; i != s; i = pre[i])
                        if(e[preh[i]].flow < f)
                            f = e[preh[i]].flow;
                    ans += f;
                    do
                    {
                        e[preh[x]].flow -= f;
                        e[preh[x]^1].flow += f;
                        x = pre[x];
                    }while(x!=s);
                }
            }
            else
            {
                if(!--vh[d[x]])
                    break;
                d[x] = n;
                for(i=now[x]=head[x]; i != -1; i = e[i].next)
                {
                    if(e[i].flow > 0 && d[x] > d[e[i].v] + 1)
                    {
                        now[x] = i;
                        d[x] = d[e[i].v] + 1;
                    }
                }
                ++vh[d[x]];
                if(x != s)
                    x = pre[x];
            }
    }
    return ans;
}

void makeGraph()
{
    int i,j;
    Init();
    for(i = 1; i <= n; i++)
    {
        for(j = 1; j <= n; j++)
        {
            if(g[i][j])
            {
                addEdge(i+n,j,INF);
                addEdge(j+n,i,INF);
            }
        }
    }
    for(i = 1; i <= n; i++)
    {
        if(!cut[i])
            addEdge(i,i+n,1);
        else
            addEdge(i,i+n,0);
    }
}

int main()
{
    int i,j;
    int s,t;
    scanf("%d %d %d",&n,&s,&t);
    memset(cut,0,sizeof(cut));
    for(i = 1; i <= n; i++)
        for(j = 1; j <= n; j++)
            scanf("%d",&g[i][j]);
    if(g[s][t])
    {
        printf("NO ANSWER!");
        return 0;
    }
    makeGraph();
    int flow = sap(s+n,t,2*n);
    printf("%d\n",flow);
    int cnt = 0;
    for(i = 1; i <= n && flow; i++)
    {
        if(i==s||i==t)
            continue;
        cut[i] = true;
        makeGraph();
        if(sap(s+n,t,2*n) == flow-1)
        {
            flow--;
            result[cnt++] = i;
        }
        else
            cut[i] = false;
    }
    for(i = 0; i < cnt; i++)
        printf("%d ",result[i]);
    printf("\n");
    return 0;
}
  

?

?

最小點割集(點連通度)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 修水县| 若羌县| 德昌县| 银川市| 蒙自县| 沂南县| 手游| 米脂县| 马鞍山市| 和田县| 文安县| 嘉义市| 富阳市| 奉贤区| 景宁| 措勤县| 舒城县| 香河县| 五莲县| 理塘县| 梨树县| 离岛区| 弋阳县| 宽甸| 渑池县| 麻栗坡县| 上饶县| 文成县| 遵义市| 阳朔县| 互助| 皮山县| 道孚县| SHOW| 都江堰市| 苍梧县| 浦东新区| 太原市| 武山县| 昌平区| 绥江县|