• <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>

            M.J的blog

            algorithm,ACM-ICPC
            隨筆 - 39, 文章 - 11, 評論 - 20, 引用 - 0
            數據加載中……

            TOJ 3446.Money Matters 并查集,路徑壓縮

                    題目大意是N個人互相有債a[i](正的表示別人欠錢,否則表示自己欠別人錢,a[i]的和保證為0),但是這N個人只有朋友間才能互相算帳,現在給出N個人的債,并且給出M個關系,即誰和誰是朋友,最后問有沒有可能所有人都把帳算清。


            Sample Input 1:                         Sample Input 2:

            5    3                                            4     2
            100                                              15
            -75                                               20
            -25                                              -10
            -42                                              -15
            42                                                0  2
            0 1                                               1  3
            1 2
            3 4

            Sample Output 1:                       Sample Output  2:

            POSSIBLE                                    IMPOSSILBE

             思路1:

                          每輸入一個關系,合并,最后從1到N,對于每一個人,找出它們的祖先,將他們的債debt加到祖先的debt

                          上。通俗的講,就是每個集合的成員都將自己的debt加到祖先上,自己歸0,最后看祖先的值是否為0;

                          最后在從1到N掃一遍如果有debt不為0的,輸出“IMPOSSIBLE”,否則“POSSIBLE”;

                          缺點:復雜度高,查詢復雜度*N,最后勉強過了,時間0.63s

            思路2:

                          路徑壓縮,每輸入一個關系,合并。最后從1到N,如果 i 的debt不為0,從 i 到 i 的祖先的路徑不斷壓縮直到

                          祖先,這樣雖然仍然是N次操作,但由于在壓縮過程中大部分成員debt歸0,故實際上進行操作的次數遠小于N.

                          最后時間為0.11,比起上一種方法有了很大提高

            Code 1:

            #include <cstdio>
            #include 
            <cstring>
            struct Node{
                    
            int father,v,num;
            }a[
            10002];
            int find(int n){
                    
            int tep,m = n;
                    
            while(n != a[n].father)
                            n 
            = a[n].father;
                    
            while(m != n){
                            tep 
            = a[n].father;
                            a[n].father 
            = n;
                            m 
            = tep;
                    }
                    
            return n;
            }
            void Union(int root1,int root2){
                    
            int t1,t2;
                    t1 
            = find(root1),t2 = find(root2);
                    
            if(t1 == t2) return ;
                    
            else{
                            
            if(a[t1].v > a[t2].v){
                                    a[t1].v 
            += a[t2].v;
                                    a[t2].father 
            = t1;
                            }
                            
            else{
                                    a[t2].v 
            += a[t1].v;
                                    a[t1].father 
            = t2;
                            }
                    }
            }
            int main()
            {
                    
            int n,m,i,j;
                    
            bool flag = false;
                    scanf(
            "%d%d",&n,&m);
                    
            for(i = 0;i < n; ++i){
                            a[i].father 
            = i,a[i].v = 0;
                            scanf(
            "%d",&a[i].num);
                    }
                    
            while(m--){
                            scanf(
            "%d%d",&i,&j);
                            Union(i,j);
                    }
                    
            for(i = 0;i < n; ++i){
                            
            int tep = find(i);
                            
            int tt = a[i].num;
                            a[i].num 
            -= tt;
                            a[tep].num 
            += tt;
                    }
                    
            for(i = 0;i < n; i++)
                            
            if(a[i].num != 0){
                                    flag 
            = true;
                                    
            break;
                            }
                    
            if(flag) printf("IMPOSSIBLE\n");
                    
            else     printf("POSSIBLE\n");
            }

            Code 2:

            #include <cstdio>
            #include 
            <cstring>
            struct Node{
                    
            int father,v,num;
            }a[
            10002];
            int find(int n){
                    
            int m = n,tep;
                    
            while(n != a[n].father)
                            n 
            = a[n].father;
                    
            while(m != n){
                            tep 
            = a[m].father;
                            
            int tt = a[m].num;
                            a[m].num 
            -= tt;
                            a[tep].num 
            += tt;
                            a[m].father 
            = n;
                            m 
            = tep;
                    }
                    
            return n;
            }
            void Union(int root1,int root2){
                    
            int t1,t2;
                    t1 
            = find(root1),t2 = find(root2);
                    
            if(t1 == t2) return ;
                    
            else{
                            
            if(a[t1].v > a[t2].v){
                                    a[t1].v 
            += a[t2].v;
                                    a[t2].father 
            = t1;
                            }
                            
            else{
                                    a[t2].v 
            += a[t1].v;
                                    a[t1].father 
            = t2;
                            }
                    }
            }
            int main()
            {
                    
            int n,m,i,j;
                    
            bool flag = false;
                    scanf(
            "%d%d",&n,&m);
                    
            for(i = 0;i < n; ++i){
                            a[i].father 
            = i,a[i].v = 0;
                            scanf(
            "%d",&a[i].num);
                    }
                    
            while(m--){
                            scanf(
            "%d%d",&i,&j);
                            Union(i,j);
                    }
                    
            for(i = 0;i < n; ++i)
                         
            if(a[i].num != 0) find(i);
                    
            for(i = 0;i < n; i++)
                            
            if(a[i].num != 0){
                                    flag 
            = true;
                                    
            break;
                            }
                    
            if(flag) printf("IMPOSSIBLE\n");
                    
            else     printf("POSSIBLE\n");
            }








            posted on 2010-07-05 21:08 M.J 閱讀(319) 評論(0)  編輯 收藏 引用

            国产婷婷成人久久Av免费高清| 国内精品久久久久久久涩爱| 中文字幕热久久久久久久| 亚洲级αV无码毛片久久精品 | 亚洲国产另类久久久精品黑人| 国产三级久久久精品麻豆三级| 国产午夜精品理论片久久| av色综合久久天堂av色综合在| 久久精品一区二区| 国产毛片欧美毛片久久久| 国产农村妇女毛片精品久久| 久久午夜无码鲁丝片秋霞| 国产亚洲精午夜久久久久久| 欧洲人妻丰满av无码久久不卡| 国产精品久久久久久久久久免费| 久久精品桃花综合| 狠狠色综合久久久久尤物| 久久香综合精品久久伊人| 亚洲精品无码久久久| 精品国产一区二区三区久久| 久久久久亚洲AV成人网人人网站| 国产精品一区二区久久精品无码 | 99久久久精品| 国产成年无码久久久久毛片| 久久天天躁狠狠躁夜夜不卡| 久久久久国产精品麻豆AR影院| 97久久天天综合色天天综合色hd| 久久人做人爽一区二区三区 | 性高湖久久久久久久久| 亚洲一级Av无码毛片久久精品| 狠狠综合久久综合中文88| 九九久久精品国产| 精品久久人人做人人爽综合| 国产成人香蕉久久久久| 亚洲天堂久久精品| 国产亚州精品女人久久久久久| 精品人妻伦九区久久AAA片69| 三级韩国一区久久二区综合| 亚洲人成无码久久电影网站| 久久综合九色综合欧美就去吻| 一本色道久久88综合日韩精品 |