zoukankan      html  css  js  c++  java
  • 最近整理的模板

    
    
    dfs  
     
     
     //http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3631
     #include<cstdio>
     #include<cstring>
     #include<algorithm>
     using namespace std;
     
     int a[40];
     int b[40];
     int ans;
     int n, m;
     /*
     void dfs(int k, int sum)
     {
         if(ans == m)return;
         if(k == 0){
             ans = max(sum, ans);
             return;
         }
         if(a[k] + sum <= m)
         {
             if(b[k] + sum <= m)
             {
                 ans = max(ans, b[k] + sum);
                 return;
             }else{
                 ans = max(ans, sum + a[k]);
                 dfs(k-1, sum);
                 dfs(k-1, sum + a[k]);
             }
         }else{
             ans = max(ans, sum);
             dfs(k-1, sum);
         }
     }
     int main(){
         while(~scanf("%d%d", &n, &m))
         {
             for(int i = 1; i <= n; i ++)  scanf("%d", a + i);
             sort(a+1, a +1+ n);
             //for(int i = 1; i <= n;i ++)printf("%d\n", a[i]);
             int count = 1;
             for(int i = 1; i <= n; i ++) if(a[i] <= m) a[count++] = a[i];
             n = count-1;
             //printf("%d\n", n);
             //for(int i = 1; i <= n;i ++)printf("%d\n", a[i]);
             b[1] = a[1];
             for(int i = 2; i <= n; i ++)  b[i] = a[i] + b[i-1];
             //for(int i = 1; i <= n;i ++)printf("%d\n", b[i]);
             ans = 0;
             dfs(n, 0);
             printf("%d\n", ans);
         }
         return 0;
     }
     */
     
     void dfs(int id, int sum)
     {
         if(ans == m)return;//为什么少这一句会T  ?
         if(sum > ans ) ans = sum;
         for(int i = id; i < n; i ++)
         {
             if(sum + a[i] <= m)
             dfs(i+1, sum + a[i]);
         }
     }
     int main()
     {
         while(~scanf("%d%d", &n, &m))
         {
             int s = 0;
             for(int i = 0; i < n; i ++)
             {
                 scanf("%d", a + i);
                 s += a[i];
             }
             if(s <= m)
             {
                 printf("%d\n", s);
                 continue;
             }
             //memset(vis, 0, sizeof(vis));
             sort(a, a + n);
             ans = -1;
             dfs(0,0);
             if(ans == -1)
             puts("0");
             else
             printf("%d\n", ans);
         }
         return 0;
     }
     
     
     
     
     
     
     
     bfs 
     
     Matrix:
     struct point{
         int x, y;
         int step;
     };
     int dir[4][2] = {
    , 0,
         -1, 0,
    , 1,
    , -1
     };
     void bfs(point start){
         queue < point > q;
         q.push(start);
         while(!q.empty()){
             point tmp = q.front(); q.pop();
             for(int i = 0; i < 4; i ++){
                 int x = tmp.x + dir[i][0];
                 int y = tmp.y + dir[i][1];
                 if(x < 0 || x >= n || y < 0 || y >= m)
                   continue;
                 if(vis[x][y] == 1)
                   continue;
                 if(map[x][y] == '#')
                   continue;
                 point now;
                 now.x = x, now.y = y, now.step = tmp.step ++;
                 q.push(now);
             }
         }
     }
     
     
     const int maxn = 50000 + 10;
     struct edge{
         int to, w;
         edge * next;
     }*list[maxn];
     void add_edge(int u, int v, int w){
         edge *tmp = new edge;
         tmp->to = v;
         tmp->w = w;
         tmp->next = list[u];
         list[u] = tmp;
     }
     void bfs(int start){
         queue < int > q;
         q.push(start);
         while(!q.empty()){
             int hd = q.front(); q.pop();
             edge *tmp = list[hd];
             while(tmp != NULL){
                 if(tmp->to  @#$%^){
                     q.push(tmp->to);
                 }
                 tmp = tmp->next;
             }
         }
     }
     
     
     
     
     背包:
     
     
     vodi zero_one_pack(int cost, int weight){
         for(int i = v; i >= cost; i --){//v是最大值
             dp[i] = max(dp[i], dp[i - cost] + weight);
         }
     }
     
     void complete_pack(int cost, int weight){
         for(int i = cost; i <= v; i ++){
             dp[i] = max(dp[i], dp[i - cost] + weight);
         }
     }
     
     void multipack(int cost, int weight, int amount){
         if(amount * cost >= v){
             complete_pack(cost, weight);
             return;
         }
         int k = 1;
         while( k < amount){
             zero_one_pack(cost * k, weight * k);
             amount -= k;
             k <<= 1;
         }
         zero_one_pack(amount * cost, amount * weight);
     }
     
     
     
     
     AOV网络,Topsort
     
     #include<cstdio>
     #include<cstring>
     const int maxn = 50000 + 10;
     struct edge{
         int to, w;
         edge * next;
     }*list[maxn];
     void add_edge(int u, int v,int w){
         edge *tmp = new edge;
         tmp->to = v;
         tmp->w = w;
         tmp->next = list[u];
         list[u] = tmp;
     }
     int n, m;
     int ind[maxn];//入度
     char output[100];
     void topsort(){
         int top = -1;
         edge *tmp;
         bool bcycle = false;//判断是否存在有向环
         int pos = 0;//写入output数组的位置
         for(int i = 0; i < n; i ++){//入度为0的顶点入栈
             if(ind[i] == 0){
                 ind[i] = top;
                 top = i;
             }
         }
         for(int i = 0; i < n; i ++){
             if(top == -1){
                 bcycle = true;
                 break;
             }else{
                 int j = top;
                 top = ind[top];
                 pos += sprintf(output + pos , "%d ", j + 1);
                 tmp = list[j];
                 while(tmp != NULL){
                     int k = tmp->to;
                     if((-- ind[k]) == 0){
                         ind[k] = top;
                         top = k;
                     }
                     tmp = tmp->next;
                 }
             }
         }
         if(bcycle)
           puts("network has a cycle!");
         else{
             output[strlen(output) - 1] = 0;
             printf("%s\n", output);
         }
     }
     int main(){
         while(~scanf("%d%d", &n ,&m)){
             memset(list, 0, sizeof(list));
             memset(ind, 0, sizeof(ind));
             memset(output, 0, sizeof(output));
             for(int i = 0; i < m; i ++){
                 int u, v;
                 scanf("%d%d", &u, &v);
                 u--; v--;
                 ind[v] ++;
                 add_edge(u, v, 0);
             }
             topsort();
             for(int i = 0; i < n; i ++){
                 edge *tmp = list[i];
                 while(tmp != NULL){
                     list[i] = tmp->next;
                     delete tmp;
                     tmp = list[i];
                 }
             }
         }
         return 0;
     }
     /*
     8 
     2
     4
     6
     2
     6
     1
     2
     6
     8
     3
     2
     5
     4
     2
     6
     4
     6
     1 4 3 2 6
     network has a cycle!
     */
     
     
     //http://poj.org/problem?id=2585
     #include<cstdio>
     #include<cstring>
     #include<string>
     using namespace std;
     
     string cover[4][4];
     void init(){
         /*
         for(int i = 0; i < 4; i ++){
             for(int j = 0; j < 4; j ++)
               cover[i][j].erase();
         }
         */
         for(int k = 1; k <= 9; k ++){
             int i = (k-1) / 3;
             int j = (k-1) % 3;
             cover[i][j] += char(k + '0');
             cover[i+1][j] += char(k + '0');
             cover[i][j+1] += char(k + '0');
             cover[i+1][j+1] += char(k + '0');
         }
     }
     int ind[10];
     bool g[10][10];
     int screen[5][5];
     bool exist[10];
     int t = 0;
     void calc(){
         memset(ind, 0, sizeof (ind));
         memset(g, 0, sizeof (g));
         memset(exist, 0, sizeof (exist));
         t = 0;
         for(int i = 0; i < 4; i ++){
             for(int j = 0; j < 4; j ++){
                 int k;
                 scanf("%d", &k);
                 screen[i][j] = k;
                 if(!exist[k]) t ++;
                 exist[k] = true;
             }
         }
     }
     void build(){
         for(int i = 0; i < 4; i ++){
             for(int j = 0; j < 4; j ++){
                 for(int k = 0; k < cover[i][j].length(); k ++){
                     /*
                     if( (g[screen[i][j]][cover[i][j][k]-'0'] == 0) &&
                                 screen[i][j] != cover[i][j][k] - '0'){
                         g[screen[i][j]][cover[i][j][k]-'0'] = true;
                         ind[cover[i][j][k] - '0'] ++;
                     }
                     */
                     int u = screen[i][j];
                     int v = cover[i][j][k]-48;
                     if(g[u][v] == 0 && u != v){
                         g[u][v] = true;
                         ind[v] ++;
                     }
                 }
             }
         }
     }
     bool check(){
     /*
         for(int j = 0; j < t; j ++){
             int i = 1;
             while( !exist[i] || ( i <= 9 && ind[i] >0))
               i ++;//这个很好
             if(i > 9)return false;//说明入度都大于0了,那么就存在环了 
             exist[i] = false;
             int k = i;
             for(i = 1; i <= 9; i++){
                 if(exist[i] && g[k][i])
                   ind[i] --;
             }
         }
         return true;
     */
        // for(int i = 1; i <= 9; i ++)printf("++  %d %d\n", i, ind[i]);
         for(int i = 1; i <= 9; i ++){
             for(int j = 1; j <= 9; j ++){
                 if(ind[j] == 0){
                     ind[j] = -1;
                     for(int k = 1; k <= 9; k ++){
                         if(g[j][k] == false) continue;
                         ind[k] --;
                     }
                 }
             }
         }
         //for(int i = 1; i <= 9; i ++)printf("--  %d %d\n", i, ind[i]);
         int flag = 0;
         for(int i = 1; i <= 9; i ++){
             if(ind[i] != -1){
                 flag = 1;
                 break;
             }
         }
         if(flag)
           return false;
         else
           return true;
     
     }
     int main(){
         init();
         char s[15];
         while(~scanf("%s", s)){
             if(strcmp(s, "ENDOFINPUT") == 0) break;
             calc();
             build();
             if(check())
               puts("THESE WINDOWS ARE CLEAN");
             else
               puts("THESE WINDOWS ARE BROKEN");
             scanf("%s", s);
         }
         return 0;
     }
     
     #include<cstdio>
     #include<cstring>
     
     char map[2010][2010];
     int ind[2010];
     int vis[2010];
     int main(){
         int tcase;
         scanf("%d", &tcase);
         int z = 1;
         while(tcase --){
             int n;
             scanf("%d", &n);
             memset(vis, -1, sizeof vis);
             for(int i = 0; i < n;i  ++){
                    scanf("%s", map[i]);
                 for(int j = 0; map[i][j]; j ++)
                   if(map[i][j] == '1')
                     ind[j] ++;
             }
             int flag = 0;
             for(int i = 0; i < n; i ++){
                 int j = 0;
                 while(j < n && ind[j] != 0)//找到第一个入度为0的并且没有进入栈的点
                   j ++;
                 if(j >= n){
                     flag = 1;
                     break;
                 }
                 ind[j] --;
                 for(int k = 0; map[j][k]; k ++){
                     if(map[j][k] == '1'){
                         ind[k] --;
                     }
                 }
             }
             printf("Case #%d: ", z++);
             if(flag)
               puts("Yes");
             else
               puts("No");
         }
         return 0;
     }
     
     
     AOE网络,最长路,关键路径
     
     
     #include<cstdio>
     #include<cstring>
     
     const int maxn = 10000;//顶点个数最大值
     const int maxm = 10000;//边数最大值
     struct node{
         int to, w, id;//边的另一个顶点,持续时间,活动序号
         int next;
     }list1[maxn], list2[maxn];
     int p1[maxm], p2[maxm];//入边表,出边表
     int ind1[maxn], ind2[maxn];//入度, 出度
     int Ee[maxn];//各事件的最早可能开始时间
     int El[maxn];//各事件的最迟允许开始时间
     int e[maxm];//各活动的最早可能开始时间
     int l[maxm];//各活动的最迟允许开始时间
     int n, m;
     void criticalpath(){
         int top1 = -1;
         memset(Ee, 0, sizeof Ee);
         for(int i = 0; i < n; i ++){
             if(ind1[i] == 0){
                 ind1[i] = top1;
                 top1 = i;
             }
         }
         for(int i = 0; i < n; i ++){
             if(top1 == -1){
                 printf("network has a cycle!\n");
                 return;
             }
             int j = top1;
             top1= ind1[top1];
             for(int k = p1[j]; k != -1; k = list1[k].next){
                 int v = list1[k].to;
                 if( -- ind1[v] == 0){
                     ind1[v] = top1;
                     top1 = v;
                 }
                 if(Ee[j] + list1[k].w > Ee[v])
                   Ee[v] = Ee[j] + list1[k].w;
             }
         }
         int top2 = -1;
         for(int i = 0; i < n; i ++){
             El[i] = Ee[n-1];
             if(ind2[i] == 0){
                 ind2[i] = top2;
                 top2 = i;
             }
         }
         for(int i = 0; i < n; i ++){
             int j = top2;
             top2 = ind2[top2];
             for(int k = p2[j]; k != -1; k = list2[k].next){
                 int v = list2[k].to;
                 if( -- ind2[v] == 0){
                     ind2[v] = top2;
                     top2 = v;
                 }
                 if( El[j] - list2[k].w < El[v])
                   El[v] = El[j] - list2[k].w;
             }
         }
         memset(e, 0, sizeof e);
         memset(l, 0, sizeof l);
         for(int i = 0; i < n;i ++){
             for(int k = p1[i]; k != -1; k = list1[k].next){
                 //puts("Asdf");
                 int v = list1[k].to;
                 int id = list1[k].id;
                 e[id] = Ee[i];
                 l[id] = El[v] - list1[k].w;
                 //printf("%d %d\n", e[id], l[id]);
                 if(e[id] == l[id])
                   printf("a%d : %d->%d\n", id, i, v);
             }
         }
     }
     void init(){
         memset(list1, 0, sizeof list1);
         memset(list2, 0, sizeof list2);
         memset(ind1, 0, sizeof ind1);
         memset(ind2, 0, sizeof ind2);
         memset(p1, -1, sizeof p1);
         memset(p2, -1, sizeof p2);
     }
     int main(){
         init();
         scanf("%d%d", &n, &m);
         int index1 = 0;
         int index2 = 0;
         for(int i = 0; i < m; i ++){
             int u, v, w;
             scanf("%d%d%d", &u, &v, &w);
             ind1[v] ++;
             list1[index1].to = v;
             list1[index1].w = w;
             list1[index1].id = i + 1;
             list1[index1].next = p1[u];
             p1[u] = index1 ++;
     
             ind2[u] ++;
             list2[index2].to = u;
             list2[index2].w = w;
             list2[index2].id = i + 1;
             list2[index2].next = p2[v];
             p2[v] = index2 ++;
         }
         criticalpath();
         return 0;
     }
     /*
    
     6
     4
     5
     1
     1
     2
     9
     7
     4
     2
     4
     
     a1 : 0->1
     a4 : 1->4
     a8 : 4->7
     a7 : 4->6
     a10  6->8
     a11 : 7->8
     */
    
    
    并查集,kruckal
    
    int pre[110];
    struct edge{
        int u,v,w; 
        friend bool operator <(const edge &a, const edge &b){
            return a.w < b.w;
        }
    }e[11000];
    int find(int x){
        int s;//查找位置
        for(s = x; pre[s] >= 0; s = pre[s]);
        while(x != s){//压缩路径,使后续的查找操作加速
            int t = pre[x];
            pre[x] = s;
            x = t;
        }
        return s;
    }
    void Union(int x, int y){
        int u = find(x);
        int v = find(y);
        if(u == v) return;//如果在同一棵树上
        if(pre[u] > pre[v]){
            pre[u] += pre[v];
            pre[v] = u;
        }else{
            pre[v] += pre[u];
            pre[u] = v;
        }
    }
    void kruskal(){
        int sumweight = 0;//生成树的权值
        int num = 0;//已选用的边的数目
        memset(pre, -1, sizeof pre);//初始化数组,重要!!!
        for(int i = 0; i < m; i ++){
            int u = e[i].u;
            int v = e[i].v;
            if(find(u) != find(v)){
                suweight += e[i].w;
                num ++;
                Union(u, v);
            }
            if(num >= n - 1)
              break;
        }
        printf("%d\n", sumweight);
    }
    //注意要先给边排序,按从小大到
    
    
    Kruskal 和 prime
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int inf = 0x3fffffff;
    
    int pre[200];
    struct edge{
        int u, v, w;
        friend bool operator < (const edge &a, const edge &b){
            return a.w < b.w;
        }
    }a[200];
    int find(int x){
        int s;
        for(s = x; pre[s] >= 0; s = pre[s]);
        while(s != x){
            int t = pre[x];
            pre[x] = s;
            x = t;
        }
        return s;
    }
    void Union(int x, int y){
        int u = find(x);
        int v = find(y);
        if(u == v)return;
        if(pre[u] > pre[v]){
            pre[u] += pre[v];
            pre[v] = u;
        }else{
            pre[v] += pre[u];
            pre[u] = v;
        }
    }
    
    int e[200][200];
    char op[3];
    int n;
    int visit[200];
    int dist[200];
    int prim(){
        memset(visit, 0, sizeof(visit));
        for(int i = 0; i < n; i++){
            dist[i] = e[0][i];
        }
        dist[0] = 0;
        visit[0] = 1;
        //for(int i = 0; i < n; i++)printf("%d ",dist[i]);puts("");
        int sum = 0;
        //puts("asdf");
        for(int i = 0; i < n - 1; i++){
            int min_num = inf;
            int v;
            for(int j = 0; j < n; j++){
                if(!visit[j] && dist[j] < min_num){
                    min_num = dist[j];
                    v = j;
                }
            }
            //printf("--   %d %d\n", v, min_num);
            visit[v] = 1;
            sum += min_num;
            for(int j = 0; j < n; j++){
                if(!visit[j] && e[v][j] != 0 && e[v][j] < dist[j]){
                    dist[j] = e[v][j];
                }
            }
        }
        //for(int i = 0; i < n; i++)printf("%d ", dist[i]);puts("");
        return sum;
    }
    
    
    int m;
    
    
    int kruskal(){
        memset(pre, -1, sizeof(pre));
        int num = 0;
        int sum = 0;
        for(int i = 0; i < m; i++){
            int u = a[i].u;
            int v = a[i].v;
            if(find(u) != find(v)){
                num ++;
                sum += a[i].w;
                Union(u,v);
            }
            if(num >= n - 1)break;
        }
        return sum;
    }
    int main(){
        while(scanf("%d", &n), n){
            int t;
            memset(e, 0 ,sizeof(e));
            m = 0;
            for(int i = 0; i < n-1; i++){
                scanf("%s%d", op, &t);
                int u = op[0] - 65;
                int tt;
                //puts("asdfsdf");
                while(t--){
                    scanf("%s%d", op, &tt);
                    int v = op[0] - 65;
                    e[u][v] = e[v][u] = tt;
                    a[m].u = u;
                    a[m].v = v;
                    a[m++].w = tt;
                }
            }
            sort(a, a+m);
            for(int i = 0; i < n; i++){
                for(int j = 0; j < n; j++){
                    if(e[i][j] == 0)
                        e[i][j] = inf;
                }
            }
            //printf("%d\n", prim());
            printf("%d\n", kruskal());
        }
        return 0;
    }
    
    
    
    
    
    
    http://acm.hdu.edu.cn/showproblem.php?pid=4325
    
    离散化 + unique + lower_bound
    
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 100000 + 10;
    int a[maxn], b[maxn], c[maxn];
    int d[maxn<<2];
    int e[maxn<<2];
    int main(){
        //freopen("1006.in", "r", stdin);freopen("out.out", "w", stdout);
        int tcase;
        scanf("%d", &tcase);
        int z = 1;
        while(tcase --){
            int n, m;
            scanf("%d%d", &n, &m);
            int cnt = 0;
            for(int i = 0; i < n;i  ++){
                scanf("%d%d", a+i, b+i);
                d[cnt++] = a[i];
                d[cnt++] = b[i];
            }
            for(int i = 0; i < m; i ++){
                scanf("%d", c+i);
                d[cnt++] = c[i];
            }
            sort(d, d + cnt);
            int tmp = unique(d,d + cnt) - d;
            //printf("----------- %d\n", tmp);
            cnt = tmp;
            int count = 0;
            memset(e, 0, sizeof e);
            for(int i = 0; i < n;i ++){
                int l = lower_bound(d, d+cnt, a[i]) - d;
                int r = lower_bound(d, d+cnt, b[i]) - d;
                for(int j = l; j <= r; j ++){
                    e[j] ++;
                }
            }
            printf("Case #%d:\n", z++);
            for(int i = 0; i < m; i ++){
                int pos = lower_bound(d, d+cnt, c[i]) - d;
                printf("%d\n", e[pos]);
            }
        }
        return 0;
    }
    
    http://poj.org/problem?id=1679
    
    # include <iostream>
    # include <cstdio>
    # include <algorithm>
    # include <cstring>
    using namespace std;
    
    
    //先求出最小生成树,然后删除这棵树上的每条边求MST,求的时候要判断是否是MST
    struct edge{
        int u, v, w, f;
        friend bool operator < (const edge &a, const edge &b){
            return a.w < b.w;
        }
    }e[100 * 100 + 10];
    int pre[110];
    int n, m;
    int find(int x){
        int s;
        for(s = x; pre[s] >= 0; s = pre[s]);
        while(s != x){
            int t = pre[x];
            pre[x] = s;
            x = t;
        }
        return s;
    }
    void Union(int x, int y){
        int u = find(x);
        int v = find(y);
        if(u == v) return;//如果在同一棵树上
        if(pre[u] > pre[v]){
            pre[u] += pre[v];
            pre[v] = u;
        }else{
            pre[v] += pre[u];
            pre[u] = v;
        }
    }
    int kruskal(int f){
        int w = 0;
        int num = 0;
        memset(pre, -1, sizeof pre);
        for(int i = 0; i < m; i ++){
            if(e[i].f == 2) continue;
            int u = e[i].u;
            int v = e[i].v;
            if(find(u) != find(v)){
                w += e[i].w;
                if(f)e[i].f = 1;
                num ++;
                Union(u, v);
            }
            if(num >= n - 1)
              break;
        }
        if(num == n-1)
        return w;
        else return -1;//说明没有找到MST
    }
    int main(){
        int tcase;
        scanf("%d", &tcase);
        while(tcase --){
            scanf("%d%d", &n, &m);
            for(int i = 0; i < m; i ++){
                scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
                e[i].f = 0;
            }
            sort(e, e + m);
            int w = kruskal(1);
            int flag = 0;
            for(int i = 0; i < m; i ++){
                if(e[i].f == 0)continue;
                e[i].f ++;
                int tmp = kruskal(0);
                e[i].f --;
                //printf("%d ---\n", tmp);
                if(tmp != -1 && tmp == w){
                    flag = 1;
                    break;
                }
            }
            if(flag)
              puts("Not Unique!");
            else
              printf("%d\n", w);
        }
        return 0;
    }
    
    
    /*
    //牛人做法,拿来当模板用
    int const INF=1000000000;
    int const maxn=105;
    int mark[maxn],map[maxn][maxn],mst[maxn];
    int n,m;
    void prim(){
        int i,j,k,ans=0,min,v,flag=0;
        for (i=1;i<=n;i++){
            mark[i]=0;
            mst[i]=map[1][i];
        }
        mark[1]=1;
        for (i=1;i<n;i++){
            min=INF;
            for (j=1;j<=n;j++){
                if (!mark[j] && mst[j]<min){
                    min=mst[j];
                    v=j;
                }
            }
            k=0;
            //------------------------------
            //如果要选的点到已选的点,还有一条边权值相同,就 NO 了
            for (j=1;j<=n;j++){
                if (mark[j] && min==map[v][j])k++;
            }
            if (k>1){flag=1;break;}
            //------------------------------
            ans+=min;
            mark[v]=1;
            for (j=1;j<=n;j++){
                if (!mark[j] && map[v][j]<mst[j])mst[j]=map[v][j];
            }
        }
        if (flag)cout<<"Not Unique!"<<endl;
        else cout<<ans<<endl;
    }
    int main()
    {
        int cas,i,j,p,q,w;
        cin>>cas;
        while (cas--)
        {
            cin>>n>>m;
            for (i=1;i<=n;i++)
                for (j=1;j<=n;j++)
                    map[i][j]=INF;
            while (m--)
            {
                cin>>p>>q>>w;
                map[q][p]=map[p][q]=w;
            }
            prim();
        }
        return 0;
    }
    */
    
    
    树状数组
    HDU1166敌兵布阵
    
    #include<cstdio>
    #include<cstring>
    const int maxn = 50000 + 10;
    int a[maxn], c[maxn];
    int n;
    inline int lowbit(int x){
        return x&(-x);
    }
    inline void update(int pos, int x){
        while(pos <= n){
            c[pos] += x;
            pos += lowbit(pos);
        }
    }
    inline int query(int end){
        int sum = 0;
        while(end > 0){
            sum += c[end];
            end -= lowbit(end);
        }
        return sum;
    }
    int main(){
        int tcase;
        scanf("%d", &tcase);
        int z = 1;
        while(tcase --){
            scanf("%d", &n);
            memset(a, 0, sizeof a);
            memset(c, 0, sizeof c);
            for(int i = 1; i <= n;i ++){
                scanf("%d", a + i);
                update(i, a[i]);
            }
            printf("Case %d:\n", z++);
            char op[10];
            while(scanf("%s", op) && op[0] != 'E'){
                int i, j;
                scanf("%d%d", &i, &j);
                switch(op[0]){
                    case 'Q':
                        printf("%d\n", query(j) - query(i - 1));
                        break;
                    case 'A':
                        update(i, j);
                        a[i] += j;
                        break;
                    case 'S':
                        update(i, -j);
                        a[i] -= j;
                }
            }
        }
        return 0;
    }
    
    最短路
    
    邻接表:
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1000;
    //定义最大值即0x7fffffff
    const int inf=~0U>>1;
    int path[maxn];//保存路径
    int visit[maxn];//标记是否访问
    int dist[maxn];//保存距离,即结果
    int shortest[maxn];//保存倒找的结点
    //边的结构体
    struct edge{
        int to,w;
        edge*next;
    }*list[maxn];
    int n,m;
    //按最短路长短排序
    struct sort__{
        int len;
        int num;
        //重载运算符
        friend bool operator <(const sort__&a,const sort__&b){
            if(a.len!=b.len)return a.len<b.len;else
            a.num<b.num;
        }
    }ans[maxn];
    //加边
    void add_edge(int u,int v,int w){
        edge *tmp=new edge;
        tmp->to=v;
        tmp->w=w;
        tmp->next=list[u];
        list[u]=tmp;
    }
    //dijkstra算法实现
    void dijk(int u){
        edge *tmp=list[u];
        for(int i=1;i<=n;i++)dist[i]=inf;
        memset(visit,0,sizeof(visit));
        memset(path,-1,sizeof(path));
        while(tmp!=NULL){
            int v=tmp->to;
            dist[v]=tmp->w;
            path[v]=u;
            tmp=tmp->next;
        }
        visit[u]=1;
        dist[u]=0;
        for(int i=1;i<n;i++){
            int min=inf,uu=u;
            for(int j=1;j<=n;j++){
                if(!visit[j] && dist[j]<min){
                    uu=j;
                    min=dist[j];
                }
            }
            visit[uu]=1;
            tmp=list[uu];
            while(tmp!=NULL){
                int v=tmp->to;
                if(!visit[v] && dist[uu]+tmp->w<dist[v]){
                    dist[v]=dist[uu]+tmp->w;
                    path[v]=uu;
                }
                tmp=tmp->next;
            }
        }
    }
    //递归输出
    void dfs(int i)
    {
        //if(i==-1)return;
        if(path[i]==i) return;
        dfs(path[i]);
        printf("%d--->",path[i]);
    }
    int main(){
        //freopen("最短路.txt","r",stdin);
        while(~scanf("%d%d",&n,&m)){
            memset(list,NULL,sizeof(list));
            for(int i=0;i<m;i++){
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                //无向图要加双向边
                add_edge(u,v,w);
                add_edge(v,u,w);
            }
            dijk(1);
            //for(int i = 1; i <= n;i ++)printf("%d\n", path[i]);
    
            //保存信息然后排序
            for(int i=1;i<=n;i++){
                ans[i].num=i;
                ans[i].len=dist[i];
            }
            sort(ans+1,ans+1+n);
    
            for(int i=2;i<=n;i++){
                //printf("%d\n",dist[i]);
                printf("%d\n",ans[i].len);
    
                dfs(i);
                printf("%d\n",i);
                puts("");
    
    /*
                //非递归输出
                memset(shortest,0,sizeof(shortest));
                int k=1;
                shortest[k]=ans[i].num;
                while(path[shortest[k]]!=-1){
                    k++;
                    shortest[k]=path[shortest[k-1]];
                }
                k++;
                shortest[k]=0;
                for(int j=k-1;j>1;j--){
                    printf("%d-->",shortest[j]);
                }
                printf("%d\n\n",shortest[1]);
    */
            }
        }
        return 0;
    }
    
    
    矩阵:
    
    const int maxn = 100;//顶点个数
    const int inf = ~0U>>1;
    int visit[maxn];//标记
    int dist[maxn];//记录从当前点开始最短路到各点的距离
    int path[maxn];//记录路径
    int g[maxn][maxn];
    void dijk(int u){
        for(int i = 0; i < n; i ++){
            dist[i] = g[u][i];
            visit[i] = 0;
            if( i != u && dist[i] < inf)
              path[i] = u;
            else
              path[i] = -1;
        }
        visit[u] = 1;
        dist[u] = 0;
        for(int i = 0; i < n - 1; i ++){//确定n-1条最短路径
            int min_num = inf, v;
            for(int j = 0; j < n; j ++){
                if(!visit[j] && dist[j] < min_num){
                    v = j;
                    min_num = dist[j];
                }
            }
            visit[v] = 1;
            for(int j = 0; j < n; j ++){
                if(!visit[j] && g[v][j] < inf && dist[v] + g[v][j] < dist[j]){
                    dist[j] = dist[v] + g[v][j];
                    path[j] = v;
                }
            }
        }
    }
    
    int main(){
        //读入数据
        dijk(start);
        int shortest[maxn];
        ofr(int i = 1; i <= n; i ++){
            printf("%d\t", dist[i]);
            memset(shortest, 0, sizeof shortest);
            int k = 0;
            shortest[k] = i;
            while(path[shortest[k]] != 0){
                k ++;
                shortest[k] = path[shortest[k-1]];
            }
            k ++;
            shortest[k] = 0;
            for(int j = k; j > 0; j --){
                printf("%d->", shortest[j]);
            }
            printf("%d\n", shortest[0]);
        }
        return 0;
    }
    
    
    
    SPFA
    
    #include<cstdio>
    #include<cstring>
    
    const int inf = ~0U>>1;
    const int maxn = 100;//点个数
    struct node {
        int to, w;
        int next;
    }list[maxn];
    int head[maxn];
    int n;
    int dist[maxn];
    int path[maxn];
    int visit[maxn];
    int q[maxn];
    void spfa(int src){
        for(int i = 0; i < n; i ++){
            dist[i] = inf;
            path[i] = src;
            visit[i] = 0;
        }
        dist[src] = 0;
        path[src] = src;
        visit[src] = 1;
        int qs = 0, qe = 0;
        q[qe++] = src;
        while(qs <= qe){
            int u = q[qs++];
            visit[u] = 0;
            for(int i = head[u]; i != -1; i = list[i].next){
                int v = list[i].to;
                if(dist[v] > dist[u] + list[i].w){
                    dist[v] = dist[u] + list[i].w;
                    path[v] = u;
                    if( !visit[v]){
                        q[qe++] = v;
                        visit[v] = 1;
                    }
                }
            }
        }
    }
    
    int index;
    void init(){
        index = 0;
        memset(head, -1, sizeof head);
    }
    void add_edge(int u, int v, int w){
        list[index].to = v;
        list[index].w = w;
        list[index].next = head[u];
        head[u] = index ++;
    }
    int main(){
        scanf("%d", &n);
        init();
        while(true){
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            if(u == -1 && v == -1 && w == -1) break;
            add_edge(u, v, w);
        }
        spfa(0);
        int shortest[maxn];
        for(int i = 1; i < n; i ++){
            printf("%d\t", dist[i]);
            memset(shortest, 0, sizeof shortest);
            int k = 0;
            shortest[k] = i;
            while(path[shortest[k]] != 0){
                k ++;
                shortest[k] = path[shortest[k-1]];
            }
            k ++;
            shortest[k] = 0;
            for(int j = k; j > 0; j --){
                printf("%d->", shortest[j]);
            }
            printf("%d\n", shortest[0]);
        }
        return 0;
    }
    /*
    
     1 6
     2 5
     3 5
     4 -1
     1 -2
     4 1
     2 -2
     5 -1
     6 3
     6 3
    -1 -1 -1
       0->3->2->1
       0->3->2
       0->3
       0->3->2->1->4
       0->3->5
       0->3->2->1->4->6
    */
    
    
    
    
    
    
    
    floyd
    
    
    const int inf = ~0U>>1;
    const int maxn = 100;
    int n;
    int g[maxn][maxn];
    int path[maxn][maxn];
    void floyd(){
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                if(i != j && g[i][j] < inf)
                  path[i][j] = i;
                else
                  path[i][j] = -1;
            }
        }
        for(int k = 0; k < n; k ++){
            for(int i = 0; i < n; i ++){
                for(int j = 0; j < n; j ++){
                    if(k == i || k == j)
                      continue;
                    if(g[i][k] + g[k][j] < g[i][j]){
                        g[i][j] = g[i][k] + g[k][j];
                        path[i][j] = path[k][j];
                    }
                }
            }
        }
    }
    int main(){
    
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                if(i == 0) g[i][j] = 0;
                else g[i][j] = inf;
            }
        }
        floyd();
        int shortest[maxn];
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                if(i == j) continue;
                printf("%d=>%d\t%d\t", i, j, g[i][j]);
                memset(shortest, 0, sizeof shortest);
                int k = 0; 
                shortest[k] = j;
                while(path[i][shortest[k]] != i){
                    k ++;
                    shortest[k] = path[i][shortest[k-1]];
                }
                k ++;
                shortest[k] = i;
                for(int t = k; t > 0; t --){
                    printf("%d->", shortest[t]);
                }
                printf("%d\n", shortest[0]);
            }
        }
        return 0;
    }
    
    欧拉路径定理:
    )    对于无向图,存在欧拉通路的充要条件:图连通,所有点奇度仅有两个或者0个,两个的是通路,0个的是回路
    )    对于有向图,存在欧拉通路的充要条件:图连通,出入度全相等;或者,出入为1的点为起点,出入为-1的点为终点,其它点出入度相等
    
    
    欧拉路径:fleury算法//无向图!!!
    
    #include<cstdio>
    #include<cstring>
    
    int n,m;
    int e[100][100];
    int top;
    int stack[100];
    void dfs(int x){
        top ++;
        stack[top] = x;
        for(int i = 1; i <= n; i ++){
            if(e[x][i] > 0){
                e[i][x] = e[x][i] = 0;//删除此边
                dfs(i);
                break;
            }
        }
    }
    void fleury(int x){
        top = 0;
        stack[top] = x;
        while(top >= 0){
            int b = 0;
            for(int i = 1; i <= n; i ++){
                if(e[stack[top]][i] > 0){
                    b=1;
                    break;
                }
            }
            if(b == 0){//如果没有可以扩展就输出并出栈
                printf("%d->",stack[top]);
                top--;
            }
            else{
                top--;
                dfs(stack[top+1]);
            }
        }
        puts("");
    }
    int main()
    {
        int degree, num, start;//顶点的度,奇度顶点个数,欧拉回路的起点
        while(~scanf("%d%d", &n, &m)){
            memset(e, 0, sizeof(0));
            for(int i = 0; i < m; i ++){
                int s, t;
                scanf("%d%d", &s, &t);
                e[s][t] = e[t][s] = 1;
            }
            num = 0, start = 1;
            //如果存在奇度顶点,则从奇度顶点出发,否则从顶点0出发
            for(int i = 1; i <= n; i ++){
                degree = 0;
                for(int j = 1; j <= n; j ++){
                    degree += e[i][j];
                }
                if(degree%2) start = i, num++;
            }
            if(num == 0||num == 2) fleury(start);
            else
                puts("no");
        }
        return 0;
    }
    /*
     14
     2
     8
     3
     8
     9
     4
     5
     6
     9
     6
     7
     9
     8
     9
     11
     5
     4
     3
     5
     6
     2
     6
     2
     2
     3
     6
    
    */
    
    
    
    
    
    
    
    
    
    网络流,SAP
    
    
    //http://poj.org/problem?id=1459
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    
    const int inf = 100000000;//不要开太大
    int n, np, nc, m;
    const int maxn = 105;
    int c[maxn][maxn];//残留网络
    int s, t;
    int level[maxn], gap[maxn];//层次网络, 层结点数(用于间隙优化)
    int q[maxn], pre[maxn];//队列, 前驱
    void init_sap(){
        memset(level, 10, sizeof level);
        //for(int i = 0; i <= n ;i ++) level[i] = n + 1;
        memset(gap, 0, sizeof gap);
        int qs = 0, qe = 0;
        q[qe++] = t;
        level[t] = 0;
        gap[ level[t] ] ++;
        while(qs < qe){
            int hd = q[qs++];
            for(int i = 0; i < n; i ++){
                if(level[i] > n && c[i][hd] > 0){
                    q[qe++] = i;
                    level[i] = level[hd] + 1;
                    gap[ level[i] ] ++;
                }
            }
        }
    }
    int find_path(int u){
        for(int i = 0; i < n; i ++)
          if(c[u][i] > 0 && level[u] == level[i] + 1) return i;
        return -1;
    }
    int relabel(int u){
        int tmp = inf;
        for(int i = 0; i < n; i ++)
          if(c[u][i] > 0 && tmp > level[i] + 1)
            tmp = level[i] + 1;
        if(tmp == inf) tmp = n;
        return tmp;
    }
    int sap(){
        init_sap();
        int flow = 0;
        int u = s;
        memset(pre, -1, sizeof pre);
        while(level[s] < n){
            int v = find_path(u);//寻找允许弧
            if(v >= 0){
                pre[v] = u;
                u = v;
                if(u == t){//找到完整增广路
                    int min_flow = inf;
                    for(int i = t; i != s; i = pre[i])
                      if(min_flow > c[ pre[i] ][i]) min_flow = c[ pre[i] ][i];
                    for(int i = t; i != s; i = pre[i]){
                        c[ pre[i] ][i] -= min_flow;//正向减
                        c[i][ pre[i] ] += min_flow;
                    }
                    flow += min_flow;
                    u = s;//重新从源点找
                }
            }else{//找不到弧
                if( -- gap[ level[u] ] == 0) return flow;//更新断层 + 判断是否断层
                v = relabel(u);
                gap[v] ++;
                level[u] = v;//重新标号
                if(u != s)
                  u = pre[u];//当前弧优化
            }
        }
        return flow;
    }
    int main(){
        while(~scanf("%d%d%d%d", &n, &np, &nc, &m)){
            memset(c, 0, sizeof c);
            s = n, t = n + 1, n += 2;
            for(int i = 0; i < m; i ++){
                int u, v, w;
                scanf(" (%d,%d)%d", &u, &v, &w);
                c[u][v] = w;
            }
            for(int i = 0; i < np; i ++){
                int v, w;
                scanf(" (%d)%d", &v, &w);
                c[s][v] = w;
            }
            for(int i = 0; i < nc; i ++){
                int u, w;
                scanf(" (%d)%d", &u, &w);
                c[u][t] = w;
            }
            int flow = sap();
            printf("%d\n", flow);
        }
        return 0;
    }
    
    
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    
    const int inf = 100000000;//不要开太大
    int n, np, nc, m;
    const int maxn = 105;
    int c[maxn][maxn];//残留网络
    int s, t;
    int level[maxn], gap[maxn];//层次网络, 层结点数(用于间隙优化)
    int cur[maxn], pre[maxn];
    
    int sap(){
        memset(cur, 0, sizeof cur);
        memset(level, 0, sizeof level);
        memset(gap, 0, sizeof gap);
        int u = pre[s] = s, v;
        int flow = 0;
        int aug = inf;
        gap[s] = n;// gap[0] = n, gap[s] = t
        while(level[s] < n){
            for(v = cur[u]; v < n; v ++){
                if(c[u][v] > 0 && level[u] == level[v] + 1)
                break;
            }
            if(v < n){
                pre[v] = u;
                if(aug > c[u][v]) aug = c[u][v];
                u = cur[u] = v;
                if(u == t){
                    flow += aug;
                    for(v = t; v != s; v = pre[v]){
                        c[ pre[v] ][v] -= aug;
                        c[v][ pre[v] ] += aug;
                    }
                    aug = inf, u = s;
                }
            }else{
                int min_label = n;
                for(v = 0; v < n; v ++){
                    if(c[u][v] > 0 && min_label > level[v]){
                        cur[u] = v;
                        min_label = level[v];
                    }
                }
                if(--gap[level[u]] == 0) return flow;
                level[u] = min_label + 1;
                gap[ level[u] ] ++;
                u = pre[u];
            }
        }
        return flow;
    }
    int main(){
        while(~scanf("%d%d%d%d", &n, &np, &nc, &m)){
            memset(c, 0, sizeof c);
            s = n, t = n + 1, n += 2;
            for(int i = 0; i < m; i ++){
                int u, v, w;
                scanf(" (%d,%d)%d", &u, &v, &w);
                c[u][v] = w;
            }
            for(int i = 0; i < np; i ++){
                int v, w;
                scanf(" (%d)%d", &v, &w);
                c[s][v] = w;
            }
            for(int i = 0; i < nc; i ++){
                int u, w;
                scanf(" (%d)%d", &u, &w);
                c[u][t] = w;
            }
            int flow = sap();
            printf("%d\n", flow);
        }
        return 0;
    }
    
    #include<cstdio>
    #include<cstring>
    
    struct Edge{
        int to, next, w;
    }e[40000];
    int head[300], index;
    int n, np, nc, m;
    int s, t;
    const int maxn = 110;
    int level[maxn], gap[maxn];
    int cur[maxn], pre[maxn];
    const int inf = 10000000;
    void add_edge(int u, int v, int w){
        e[index].to = v;
        e[index].w = w;
        e[index].next = head[u];
        head[u] = index ++;
        e[index].to = u;
        e[index].w = 0;
        e[index].next = head[v];
        head[v] = index ++;
    }
    int sap(){
        int u = pre[s] = s, v;
        int flow = 0;
        int aug = inf;
        memset(gap, 0, sizeof gap);
        memset(level, 0, sizeof level);
        for(int i = 0; i < n; i ++) cur[i] = head[i];
        gap[s] = n;
        while(level[s] < n){
            bool flag = false;
            for(int i = cur[u]; i != -1; i = e[i].next){
                v = e[i].to;
                if(e[i].w > 0 && level[u] == level[v] + 1){
                    flag = true;
                    if(e[i].w < aug) aug = e[i].w;
                    pre[v] = u;
                    u = v;
                    if(u == t){
                        flow += aug;
                        while(u != s){
                            u = pre[u];
                            e[cur[u]].w -= aug;
                            e[cur[u]^1].w += aug;
                        }
                        aug = inf;
                    }
                    break;
                }
                cur[u] = e[i].next;
            }
            if(flag)continue;
            int min_label = n;
            for(int i = head[u]; i != -1; i = e[i].next){
                v = e[i].to;
                if(e[i].w > 0 && min_label > level[v]){
                    min_label = level[v];
                    cur[u] = i;
                }
            }
            if(--gap[level[u]] == 0) return flow;
            level[u] = min_label + 1;
            gap[ level[u] ] ++;
            u = pre[u];
        }
        return flow;
    }
    int main(){
        while(~scanf("%d%d%d%d", &n, &np, &nc, &m)){
            s = n, t = n + 1, n += 2;
            index = 0;
            memset(head, -1, sizeof head);
            for(int i = 0; i < m; i ++){
                int u, v, w;
                scanf(" (%d,%d)%d", &u, &v, &w);
                add_edge(u, v, w);
            }
            for(int i = 0; i < np; i ++){
                int v, w;
                scanf(" (%d)%d", &v, &w);
                add_edge(s, v, w);
            }
            for(int i = 0; i < nc; i ++){
                int u, w;
                scanf(" (%d)%d", &u, &w);
                add_edge(u, t, w);
            }
            int flow = sap();
            printf("%d\n", flow);
        }
        return 0;
    }
    
    http://poj.org/problem?id=2516
    
    最小费用最大流—邻接表
    #include<cstdio>
    #include<cstring>
    
    const int inf = 10000000;
    const int maxn = 110;
    struct Edge{
        int u, v, w, c, next;
    }e[maxn * maxn * 4];
    int head[maxn], index;
    void init_edge(){
        memset(head, -1, sizeof head);
        index = 0;
    }
    void _add_edge(int u, int v, int w, int c){
        e[index].u = u, e[index].v = v;
        e[index].w = w, e[index].c = c;
        e[index].next = head[u];
        head[u] = index ++;
    }
    void add_edge(int u, int v, int w, int c){
        _add_edge(u, v, w, c);
        _add_edge(v, u, -w, 0);
    }
    int q[1000000 + 10];
    int visit[maxn];
    int dist[maxn];
    int pre[maxn];
    int s, t, n;
    bool spfa(){
        int qs = 0, qe = 0;
        memset(visit, 0, sizeof visit);
        memset(pre, -1, sizeof pre);
        for(int i = s; i <= t; i ++) dist[i] = inf;
        q[qe++] = s;
        visit[s] = 1;
        dist[s] = 0;
        while(qs < qe){
            int now = q[qs++];
            visit[now] = 0;
            for(int i = head[now]; i + 1; i = e[i].next){
                int v = e[i].v;
                if(!e[i].c) continue;
                if(dist[v] == inf || dist[now] + e[i].w < dist[v]){
                    dist[v] = dist[now] + e[i].w;
                    pre[v] = i;
                    if(!visit[v]){
                        visit[v] = 1;
                        q[qe++] = v;
                    }
                }
            }
        }
        return dist[t] != inf;
    }
    int min_cost(){
        int cost = 0;
        while(spfa()){
            int flow = inf;
            for(int i = pre[t]; i != -1; i = pre[e[i].u])
              if(flow > e[i].c) flow = e[i].c;
            for(int i = pre[t]; i != -1; i = pre[e[i].u]){
                e[i].c -= flow;
                e[i^1].c += flow;
            }
            cost += flow * dist[t];
        }
        return cost;
    }
    int N, M, K;
    int need[maxn][maxn];
    int supply[maxn][maxn];
    int m[maxn][maxn][maxn];
    int main(){
        while(scanf("%d%d%d", &N, &M, &K), N||M||K){
            for(int i = 1; i <= N; i ++){
                for(int j  = 1; j <= K; j ++){
                    int a;
                    scanf("%d", &a);
                    need[i][j] = a;
                }
            }
            for(int i = 1; i <= M; i ++){
                for(int j = 1; j <= K; j ++){
                   int a;
                   scanf("%d", &a);
                   supply[i][j] = a;
                }
            }
            for(int i = 1; i <= K; i ++){
                for(int j = 1; j <= N; j ++){
                    for(int k = 1; k <= M; k ++){
                        int a;
                        scanf("%d", &a);
                        m[i][j][k] = a;
                    }
                }
            }
            n = N + M;
            s = 0, t = n + 1;
            int ans = 0;
            for(int k = 1; k <= K; k ++){
                init_edge();
                for(int i = 1; i <= M; i ++){
                    add_edge(s, i, 0, supply[i][k]);
                }
                for(int i = 1; i <= M; i ++){
                    for(int j = 1; j <= N; j ++){
                        add_edge(i, j + M, m[k][j][i], inf);
                    }
                }
                for(int i = 1; i <= N; i ++){
                    add_edge(i + M, t, 0, need[i][k]);
                }
                ans += min_cost();
                bool flag = 0;
                for(int i = 1 + M; i <= N + M; i ++){
                    for(int j = head[i]; j + 1; j = e[j].next){
                        int v = e[j].v;
                        if(v == t && e[j].c > 0){
                            flag = true;
                            break;
                        }
                    }
                    if(flag) break;
                }
                if(flag){
                    ans = -1;
                    break;
                }
            }
            printf("%d\n", ans);
        }
        return 0;
    }
    
    
    二分图最大匹配
    
    
    #include<cstdio>
    #include<cstring>
    
    int k, m, n;
    bool g[510][510];
    int visit[510], link[510];
    bool dfs(int u){
        for(int i = 1; i <= n; i ++){
            if(g[u][i] && !visit[i]){
                visit[i] = 1;
                if(link[i] == -1 || dfs(link[i])){
                    link[i] = u;
                    return true;
                }
            }
        }
        return false;
    }
    int max_match(){
        memset(link, -1, sizeof link);
        int ans = 0;
        for(int i = 1; i <= m; i ++){
            memset(visit, 0, sizeof visit);
            if(dfs(i))
              ans ++;
        }
        return ans;
    }
    int main(){
        while(scanf("%d", &k), k){
            scanf("%d%d", &m, &n);
            memset(g, 0, sizeof g);
            while(k --){
                int u, v;
                scanf("%d%d", &u, &v);
                g[u][v] = true;
            }
            printf("%d\n", max_match());
        }
        return 0;
    }
    
    
    http://acm.hdu.edu.cn/showproblem.php?pid=1269
    
    
    强连通分量
    #include<cstdio>
    #include<cstring>
    
    const int maxn = 10000 + 10;
    struct Edge{
        int to, next;
    }e[maxn*10];
    int head[maxn], index;
    int dfn[maxn], low[maxn];
    int belong[maxn], vis[maxn];
    int step, color;//时间戳,强连通分量个数
    
    void add_edge(int u, int v){
        e[index].to = v, e[index].next = head[u];
        head[u] = index ++;
    }
    void init_edge(){
        memset(head, -1, sizeof head);
        index= 0;
    }
    int n, m;
    int stack[maxn], top;
    void targan(int u){
        dfn[u] = low[u] = ++step;
        stack[top++] = u;
        vis[u] = 1;
        for(int i = head[u]; i != -1; i = e[i].next){
            int v = e[i].to;
            if(!dfn[v]){
                targan(v);
                if(low[u] > low[v])
                  low[u] = low[v];
            }else
              if(vis[v] && low[u] > dfn[v])
                low[u] = dfn[v];
        }
        if(dfn[u] == low[u]){
            color ++;
            int s;
            do{
                s = stack[--top];
                vis[s] = 0;
                belong[s] = color;
            }while(s != u);
        }
    }
    void solve(){
        memset(vis, 0, sizeof vis);
        memset(dfn, 0, sizeof dfn);
        memset(belong, -1, sizeof belong);
        step = color = top = 0;
        for(int i = 1; i <= n; i ++)
          if(!dfn[i])
            targan(i);
    }
    int main(){
        while(scanf("%d%d", &n, &m), n||m){
            init_edge();
            for(int i = 0; i < m; i ++){
                int u, v;
                scanf("%d%d", &u, &v);
                add_edge(u, v);
            }
            solve();
            if(color == 1)
              puts("Yes");
            else
              puts("No");
        }
        return 0;
    }
    
    
    
     
  • 相关阅读:
    Java 8实战之读书笔记五:超越Java 8
    Quartz的简单使用
    Quartz实现数据库动态配置定时任务
    Java解析Groovy和Shell的代码
    Spring学习笔记(3)——快速入门
    linux的防火墙端口配置
    气泡提示 纯CSS
    解决LINUX下SQLPLUS时上下左右键乱码问题
    redhat Enterprise Linux 6 VNC安装
    使用mount命令挂载CDROM
  • 原文地址:https://www.cnblogs.com/louzhang/p/2618884.html
Copyright © 2011-2022 走看看