LouZhang

导航

最近整理的模板


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;
}

 

 

posted on 2012-08-01 19:11  louzhang_swk  阅读(322)  评论(0编辑  收藏  举报