• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 5,  comments - 5,  trackbacks - 0
                 把自己原來做過的幾道感覺不錯(cuò)的圖論題貼過來。
                 
            [無向圖點(diǎn)雙][POJ2942]Knights of the Round Table

            題目大意:有N個(gè)騎士,給出有兩兩之間有仇恨的關(guān)系,要求安排一種環(huán)形座次使得總?cè)藬?shù)為奇數(shù)而且其實(shí)之間不會(huì)發(fā)生沖突。

                題解:首先根據(jù)給出的關(guān)系可以確定兩兩之間沒有仇恨的關(guān)系,然后根據(jù)該關(guān)系構(gòu)建圖。容易知道,最后安排的人必定在同一個(gè)點(diǎn)雙連通分量當(dāng)中(否則不會(huì)形成環(huán))。然后要在每個(gè)點(diǎn)雙當(dāng)中尋找一個(gè)奇圈。直接給出兩個(gè)霸氣的定理:1.如果一個(gè)點(diǎn)雙連通分量中存在奇圈,那么整個(gè)點(diǎn)雙連通分量的所有點(diǎn)必定也在一個(gè)奇圈中。

            2.一個(gè)點(diǎn)雙連通分量如果不是二分圖則一定包含奇圈


              1#include <iostream>
              2#include <cstdio>
              3#include <algorithm>
              4#include <vector>
              5#include <stack>
              6using namespace std;
              7int N,M;
              8bool discnt[1005][1005],Stay[1005];
              9vector<int> adj[1005];
             10int Color,Time,dfn[1005],low[1005],color[1005],bw[1005],Ans;
             11stack< pair<int,int> > Stack;
             12
             13bool isDiv(int u,int _bw){
             14    bw[u]=_bw;
             15    int i,node;
             16    for(i=0;i<adj[u].size();i++){
             17        node=adj[u][i];
             18        if(color[node]==Color){
             19            if(bw[node]==-1){
             20                if(!isDiv(node,!_bw))    return false;
             21            }

             22            else if(bw[node]==_bw) return false;
             23        }

             24    }

             25    return true;
             26}

             27
             28void dfs(int u,int fa){
             29    int i,j,node;
             30    dfn[u]=low[u]=++Time;
             31    for(i=0;i<adj[u].size();i++){
             32        node=adj[u][i];
             33        if(!dfn[node]){
             34            Stack.push(make_pair(u,node));
             35            dfs(node,u);
             36            low[u]=min(low[u],low[node]);
             37            if(low[node]>=dfn[u]){
             38                ++Color;
             39                pair<int,int> edge_1=make_pair(node,u);
             40                pair<int,int> edge_2=make_pair(u,node);
             41                while(Stack.top()!=edge_1&&Stack.top()!=edge_2&&!Stack.empty()){
             42                    color[Stack.top().first]=color[Stack.top().second]=Color;
             43                    Stack.pop();
             44                }

             45                color[Stack.top().first]=color[Stack.top().second]=Color;
             46                Stack.pop();
             47                memset(bw,-1,sizeof(bw));
             48                if(!isDiv(u,1)){
             49                    for(j=1;j<=N;j++){
             50                        if(color[j]==Color){
             51                            Stay[j]=true;
             52                        }

             53                    }

             54                }

             55            }

             56        }

             57        else if(node!=fa){
             58
             59            low[u]=min(low[u],dfn[node]);
             60        }

             61    }

             62}

             63            
             64
             65int main(){
             66
             67    while(scanf("%d%d",&N,&M)!=EOF){
             68        if(N+M==0break;
             69        int i,j,a,b;
             70        for(i=1;i<=N;i++)   adj[i].clear();
             71        memset(discnt,false,sizeof(discnt));
             72        for(i=1;i<=M;i++){
             73            scanf("%d%d",&a,&b);
             74            discnt[a][b]=discnt[b][a]=true;
             75        }

             76        for(i=1;i<=N;i++){
             77            for(j=1;j<=N;j++){
             78                if(i==j)    continue;
             79                if(!discnt[i][j]){
             80                    adj[i].push_back(j);
             81                }

             82            }

             83        }

             84        memset(dfn,0,sizeof(dfn));
             85        memset(low,0,sizeof(low));
             86       
             87        memset(Stay,0,sizeof(Stay));
             88        memset(color,0,sizeof(color));
             89        Stack=stack< pair<int,int> >();
             90        Color=0;
             91        for(i=1;i<=N;i++){
             92            if(!dfn[i]){
             93                Time=0;
             94                dfs(i,0);
             95            }

             96        }

             97        Ans=N;
             98        for(i=1;i<=N;i++)   if(Stay[i]) Ans--;
             99        printf("%d\n",Ans);
            100    }

            101    return 0;
            102}


            校賽時(shí)的I題,Special Fish

            困惑的地方:比賽時(shí)候我們想到KM,然后想起一句話,KM只能做完備匹配,于是沒有寫。后來發(fā)現(xiàn)大家都是直接一遍KM就過了,回來我寫成費(fèi)用流發(fā)現(xiàn)不行。答案不應(yīng)該是最后的cost而應(yīng)該是 Max(cost),然后被tclsm大牛質(zhì)疑了,于是有如下討論研究:

               關(guān)鍵點(diǎn):這個(gè)圖不是完備匹配。

               1)為什么KM可以直接做就AC了?KM做出來不是完備匹配么?NO!KM做出來還是完備匹配,不過對(duì)于非完備的用邊權(quán)為0的邊代替了。那么去掉這些邊權(quán)為0的邊可以么?答案是不可以,見下文

               2)用費(fèi)用流做:

               對(duì)于每個(gè)點(diǎn)i,我拆成了i和i'然后用了兩種方式建圖
            1.s-> all i cost =0 cap=1
               all i'->t cost =0 cap=1
               所有i可以攻擊j的 i->j' cost=-(vali^valj) cap=1
               做費(fèi)用流,wa掉,部分比答案小
            2.s-> all i cost =0 cap=1
               all i'->t cost =0 cap=1
               所有i可以攻擊j的 i->j' cost=vali^valj cap=1
               所有i不可以攻擊j的 i->j' cost=0 cap=1
               做費(fèi)用流 AC

            為什么會(huì)出現(xiàn)這種問題?由于我們做的是最小費(fèi)用最大流,所以前提條件是流量最大,之后費(fèi)用最小。于是這個(gè)題的關(guān)鍵點(diǎn)終于出來了--最小費(fèi)用的情況下是不是保證最大流?直觀的看貌似是的,因?yàn)槿绻钚≠M(fèi)用的情況不是最大流的話,那么由于費(fèi)用都是負(fù)數(shù),可以再找一條增廣路來減小費(fèi)用。直接看這個(gè)好像沒有什么問題,而且之前和zz討論他也以這個(gè)為論點(diǎn)。但是在說這句話的時(shí)候忘記了一個(gè)很重要的問題--后向邊!!!從后向邊走費(fèi)用一定是負(fù)數(shù)么?No!所以這么下來未必會(huì)減少費(fèi)用而最后cost也未必是答案。

            改進(jìn)方法:1.使用模型2是的原圖可以達(dá)到最大流 2.取Max (cost)

             

            感謝tclsm大牛的指點(diǎn),感謝好友zz的討論~


            POJ 3177 邊雙連通分量
            題目大意:給一個(gè)無向圖,求最少添加多少條邊可以使得任意兩個(gè)頂點(diǎn)間至少有兩條不相交的路徑。

                題解:如果存在兩個(gè)頂點(diǎn),他們之間只有一條路徑或者所有路徑相交,那么必定有橋。所以對(duì)于原圖收縮邊雙連通分量,然后形成一棵樹,答案就是樹中(葉子節(jié)點(diǎn)個(gè)數(shù)+1)/2 (正確性:不會(huì)嚴(yán)格證明,畫個(gè)圖葉子之間兩兩連一下感覺沒問題...)


             1#include <iostream>
             2#include <vector>
             3using namespace std;
             4int t,f,r,dfn[5001],low[5001],bic[5001],color,indo[5001],ans;
             5bool brige[5001][5001];
             6vector<int> adj[5001];
             7vector< pair<int,int> > Brige;
             8
             9void dfs(int u,int v){
            10    dfn[u]=low[u]=++t;
            11    int node;
            12    for(int i=0;i<adj[u].size();i++){
            13        node=adj[u][i];
            14        if(!dfn[node]){
            15            dfs(node,u);
            16            low[u]=min(low[u],low[node]);
            17            if(low[node]>dfn[u]){
            18                brige[node][u]=brige[u][node]=true;
            19                Brige.push_back(make_pair(u,node));
            20            }

            21        }

            22        else if(node!=v){
            23            low[u]=min(low[u],dfn[node]);
            24        }

            25    }

            26}

            27
            28void floodfill(int u){
            29    bic[u]=color;
            30    int node;
            31    for(int i=0;i<adj[u].size();i++){
            32        node=adj[u][i];
            33        if(!bic[node]&&!brige[u][node]){
            34            floodfill(node);
            35        }

            36    }

            37}

            38            
            39
            40int main(){
            41    scanf("%d%d",&f,&r);
            42    int i,j,a,b;
            43    for(i=1;i<=r;i++){
            44        scanf("%d%d",&a,&b);
            45        adj[a].push_back(b);
            46        adj[b].push_back(a);
            47    }

            48    dfs(1,0);
            49    for(i=1;i<=f;i++){
            50        if(!bic[i]){
            51            ++color;
            52            floodfill(i);
            53        }

            54    }

            55    for(i=0;i<Brige.size();i++){
            56        indo[bic[Brige[i].first]]++;
            57        indo[bic[Brige[i].second]]++;
            58    }

            59    for(i=1;i<=color;i++){
            60        if(indo[i]==1) ans++;
            61    }

            62    printf("%d\n",(ans+1)/2);
            63    return 0;
            64}

            posted on 2010-08-01 19:55 OpenWings 閱讀(330) 評(píng)論(0)  編輯 收藏 引用

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            隊(duì)員

            最新評(píng)論

            • 1.?re: 杭州G題的代碼
            • @此最相思
              271763295,最近事情有點(diǎn)多回復(fù)晚了不好意思
            • --fatboy_cw
            • 2.?re: 杭州G題的代碼
            • 您有QQ么 在線請(qǐng)教一下 您的代碼我好幾個(gè)沒看懂...
            • --此最相思
            • 3.?re: 杭州G題的代碼
            • @OpenWings
              這題是不是求經(jīng)過幾個(gè)連通分量?
            • --此最相思
            • 4.?re: 杭州G題的代碼
            • @此最相思
              對(duì)無向圖收縮點(diǎn)雙連通分量以后,把每個(gè)分量連接到對(duì)應(yīng)割點(diǎn)上,對(duì)于詢問用tarjan處理lca(rmq貌似還得加個(gè)虛根),然后用距離除2即可。
            • --OpenWings
            • 5.?re: 杭州G題的代碼
            • 縮點(diǎn)以后怎么處理 能說的詳細(xì)些么? 希望能舉個(gè)具體例子說說 謝謝
            • --此最相思

            閱讀排行榜

            評(píng)論排行榜

            性做久久久久久久久久久| 久久青青草原精品影院| 亚洲伊人久久精品影院| 久久久久亚洲av无码专区| 国产精品久久99| 久久亚洲高清综合| 亚洲午夜久久久久久久久久| 精品永久久福利一区二区| 91精品婷婷国产综合久久| 久久青青国产| 婷婷久久久亚洲欧洲日产国码AV| 69久久夜色精品国产69| 天天影视色香欲综合久久| 亚洲AV日韩精品久久久久久久| 热re99久久精品国产99热| 亚洲人成网站999久久久综合 | 精品久久人人做人人爽综合| 香蕉久久夜色精品国产2020| 国产亚洲色婷婷久久99精品| 欧美亚洲另类久久综合婷婷| 99久久国产热无码精品免费| 久久久精品无码专区不卡| 亚洲AV无码久久| 亚洲欧美国产精品专区久久 | 久久天天日天天操综合伊人av| 久久亚洲精品无码aⅴ大香| 国产精品美女久久久| 99久久国产亚洲综合精品| 日本福利片国产午夜久久| 日韩精品久久久久久久电影蜜臀| 久久精品国产99久久丝袜| 国产精品美女久久久m| 亚洲性久久久影院| 日本精品久久久久中文字幕8 | 亚洲伊人久久成综合人影院| 久久精品国产网红主播| 国产精品成人久久久| 国内精品久久久久久不卡影院| 99国产精品久久久久久久成人热| 日韩人妻无码一区二区三区久久99 | 欧美久久综合性欧美|