• <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 閱讀(307) 評論(0)  編輯 收藏 引用

            久久精品这里热有精品| 9191精品国产免费久久| 99久久无色码中文字幕人妻| 久久九九兔免费精品6| 国产亚洲精久久久久久无码| 国产精品久久久久久久久| 久久电影网| 无码人妻久久一区二区三区免费丨 | 精品久久久噜噜噜久久久| www.久久精品| 伊人久久大香线蕉综合网站| 国产麻豆精品久久一二三| 久久男人中文字幕资源站| 精品综合久久久久久97| 777久久精品一区二区三区无码 | 成人久久精品一区二区三区| 日韩欧美亚洲国产精品字幕久久久| 亚洲综合伊人久久大杳蕉| 久久久久亚洲精品中文字幕| 久久久久亚洲精品天堂| 99久久免费国产精品特黄| 一本久久a久久精品综合夜夜| 国产精品久久久久蜜芽| 精品久久久久中文字| 久久免费小视频| 国产人久久人人人人爽| 久久精品中文字幕一区| 久久受www免费人成_看片中文| 久久精品无码一区二区三区| 久久99精品久久久久子伦| 久久99精品久久久大学生| 久久精品国产免费观看三人同眠| 久久伊人中文无码| 久久久WWW成人免费精品| 99精品久久久久久久婷婷| 国产亚洲美女精品久久久久狼| 少妇精品久久久一区二区三区| 亚洲欧美成人综合久久久| 精品国产乱码久久久久软件| 欧美激情一区二区久久久| 久久妇女高潮几次MBA|