整理---------

整理一下以前做过的题用到的东西吧

---------

---图论------

(1) 最短路

1.堆优化的 dijkstra

hdu 2544

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

#define MP(a,b) make_pair(a,b)

typedef long long LL;
typedef pair<int,int> pii;
const int INF = (1<<30)-1;
const int maxn = 105;

int n,m;
int N,M;
int first[maxn],ecnt;
int dis[maxn];

struct Edge{
    int v,cost,nxt;
    friend bool operator < (Edge a,Edge b){
        return a.cost > b.cost;
    }
}e[maxn*maxn];

void Add_edge(int u,int v,int c){
    e[ecnt].v = v;
    e[ecnt].cost = c;
    e[ecnt].nxt = first[u];
    first[u] = ecnt++;
}

void init(){
    ecnt = 0;
    memset(first,-1,sizeof(first));
}

struct  cmp{
    bool operator () (pii a,pii b){
        return a.first > b.first;
    }
};

int Dijkstra(int s){
    priority_queue<pii,vector<pii>,cmp> PQ;
    fill(dis+1,dis+N+1,INF);
    dis[s] = 0;
    PQ.push(MP(dis[1],1));
    while(!PQ.empty()){
        pii x = PQ.top();PQ.pop();
        if(dis[x.second] < x.first) continue;
        for(int i = first[x.second];i != -1;i = e[i].nxt){
            int v = e[i].v;
            if(dis[v] > dis[x.second] + e[i].cost){
                dis[v] = dis[x.second] + e[i].cost;
                PQ.push(MP(dis[v],v));
            }
        }
    }
    return dis[N];
}

int main(){
    while(scanf("%d %d",&N,&M) != EOF){
        if(N == 0 && M == 0) break;
        init();
        for(int i = 1;i <= M;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            Add_edge(a,b,c);
            Add_edge(b,a,c);
        }
        printf("%d\n",Dijkstra(1));
    }
    return 0;
}
View Code

 2.spfa

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 using namespace std;
 8 
 9 #define MP(a,b) make_pair(a,b)
10 
11 typedef long long LL;
12 typedef pair<int,int> pii;
13 const int INF = (1<<30)-1;
14 const int maxn = 105;
15 
16 int n,m;
17 int N,M;
18 int first[maxn],ecnt;
19 int dis[maxn],inq[maxn];
20 
21 struct Edge{
22     int v,cost,nxt;
23     friend bool operator < (Edge a,Edge b){
24         return a.cost > b.cost;
25     }
26 }e[maxn*maxn];
27 
28 void Add_edge(int u,int v,int c){
29     e[ecnt].v = v;
30     e[ecnt].cost = c;
31     e[ecnt].nxt = first[u];
32     first[u] = ecnt++;
33 }
34 
35 void init(){
36     ecnt = 0;
37     memset(first,-1,sizeof(first));
38 }
39 
40 int Spfa(int s){
41     queue<int> Q;
42     memset(inq,0,sizeof(inq));
43     fill(dis+1,dis+N+1,INF);
44     Q.push(s);
45     inq[s] = 1;
46     dis[s] = 0;
47     while(!Q.empty()){
48         int x = Q.front();Q.pop();
49         inq[x] = 0;
50         for(int i = first[x];~i;i = e[i].nxt){
51             int v = e[i].v;
52             if(dis[v] > dis[x] + e[i].cost){
53                 dis[v] = dis[x] + e[i].cost;
54                 if(inq[v] == 0){
55                     inq[v] = 1;
56                     Q.push(v);
57                 }
58             }
59         }
60     }
61     return dis[N];
62 }
63 
64 int main(){
65     while(scanf("%d %d",&N,&M) != EOF){
66         if(N == 0 && M == 0) break;
67         init();
68         for(int i = 1;i <= M;i++){
69             int a,b,c;
70             scanf("%d %d %d",&a,&b,&c);
71             Add_edge(a,b,c);
72             Add_edge(b,a,c);
73         }
74         printf("%d\n",Spfa(1));
75     }
76     return 0;
77 }
View Code

 

(2)最小生成树

1.堆优化的 prim

适合稠密的图

poj 1258 输入的是 N*N的邻接矩阵

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

#define MP(a,b) make_pair(a,b)

typedef long long LL;
typedef pair<int,int> pii;
const int INF = (1<<30)-1;
const int maxn = 105;

int n,m;
int N,M;
int first[maxn],ecnt;
int dis[maxn],used[maxn];

struct Edge{
    int v,cost,nxt;
    friend bool operator < (Edge a,Edge b){
        return a.cost > b.cost;
    }
}e[maxn*maxn];

void Add_edge(int u,int v,int c){
    e[ecnt].v = v;
    e[ecnt].cost = c;
    e[ecnt].nxt = first[u];
    first[u] = ecnt++;
}

int Prim(){
    priority_queue<Edge> PQ;
    int cnt = 0,mst = 0;
    memset(used,0,sizeof(used));
    fill(dis+1,dis+N+1,INF);
    Edge s;
    s.v = 1,s.cost = 0;
    PQ.push(s);
    while(cnt < N){
        Edge x = PQ.top();PQ.pop();
        if(used[x.v]) continue;
        used[x.v] = 1;
        cnt++;
        mst += x.cost;
        for(int i = first[x.v];~i;i=e[i].nxt){
            int v = e[i].v;
            if(!used[v] && dis[v] > e[i].cost){
                dis[v] = e[i].cost;
                PQ.push(e[i]);
            }
        }
    }
    return mst;
}

void init(){
    ecnt = 0;
    memset(first,-1,sizeof(first));
}


int main(){
    while(scanf("%d",&N) != EOF){
        init();
        for(int i = 1;i <= N;i++){
            for(int j = 1;j <= N;j++){
                int tmp;
                scanf("%d",&tmp);
                if(tmp) Add_edge(i,j,tmp);
            }
        }
        printf("%d\n",Prim());
    }
    return 0;
}
View Code

 2.Kruskal

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 using namespace std;
 8 
 9 #define MP(a,b) make_pair(a,b)
10 
11 typedef long long LL;
12 typedef pair<int,int> pii;
13 const int INF = (1<<30)-1;
14 const int maxn = 105;
15 
16 int n,m;
17 int N,M;
18 int first[maxn],ecnt;
19 int dis[maxn],used[maxn],fa[maxn];
20 
21 struct Edge{
22     int u,v,cost,nxt;
23     friend bool operator < (Edge a,Edge b){
24         return a.cost < b.cost;
25     }
26 }e[maxn*maxn];
27 
28 void Add_edge(int u,int v,int c){
29     e[ecnt].u = u;
30     e[ecnt].v = v;
31     e[ecnt].cost = c;
32     e[ecnt].nxt = first[u];
33     first[u] = ecnt++;
34 }
35 
36 int find(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]);}
37 
38 int Kruskal(){
39     int mst = 0;
40     sort(e,e+ecnt);
41     for(int i = 0;i < ecnt;i++){
42         int u = e[i].u;
43         int v = e[i].v;
44         int x = find(u),y = find(v);
45         if(x != y){
46             mst += e[i].cost;
47             fa[x] = y;
48         }
49     }
50     return mst;
51 }
52 
53 void init(){
54     ecnt = 0;
55     memset(first,-1,sizeof(first));
56 }
57 
58 
59 int main(){
60     while(scanf("%d",&N) != EOF){
61         init();
62         for(int i = 1;i <= N;i++) fa[i] = i;
63         for(int i = 1;i <= N;i++){
64             for(int j = 1;j <= N;j++){
65                 int tmp;
66                 scanf("%d",&tmp);
67                 if(tmp) Add_edge(i,j,tmp);
68             }
69         }
70         printf("%d\n",Kruskal());
71     }
72     return 0;
73 }
View Code

 

(3)无向图的割顶和桥

1.割顶

加的vis[]是为了防止重边

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

typedef long long LL;
const int maxn = 100005;

int first[maxn];
int ecnt,tot;
int low[maxn],iscut[maxn],dfn[maxn];
int vis[maxn];
int N,M;

struct Edge{
    int u,v,nxt;
}e[2*maxn];

void Add_edges(int u,int v){
    e[ecnt].v = v;
    e[ecnt].nxt = first[u];
    first[u] = ecnt++;
}

void init(){
    ecnt = tot = 0;
    memset(first,-1,sizeof(first));
}

void Dfs(int p,int pre){
    low[p] = dfn[p] = ++tot;
    int son = 0;
    for(int i = first[p];~i;i = e[i].nxt){
        if(vis[i]) continue;
        vis[i] = vis[i^1] = true;
        int v = e[i].v;
        if(!dfn[v]){
            ++son;
            Dfs(v,p);
            low[p] = min(low[p],low[v]);
            if(low[v] >= dfn[p]) iscut[p] = 1;//割顶 
        }
        else low[p] = min(low[p],dfn[v]) ;
    }
    if(pre < 0 && son == 1) iscut[p] = 0;
}

void Tarjan(){
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(iscut,0,sizeof(iscut));
    memset(vis,0,sizeof(vis));
    Dfs(1,-1);
    int ans = 0;
    for(int i = 1;i <= N;i++) ans += iscut[i];
    printf("%d\n",ans);
}

int main(){
    while(scanf("%d",&N)!=EOF && N){
        init();
        int a,b;
        char c;
        while(scanf("%d",&a)!=EOF&&a){
            while(scanf("%d%c",&b,&c)!=EOF){
                Add_edges(a,b);
                Add_edges(b,a); 
                if(c=='\n') break;
            }
        }
        
        Tarjan();
        
    }
    return 0;
}
View Code

 2.桥

ZOJ 2588

搞不清楚重边搞了好久---

vis[]标记的是对称边,,试用于有重边的情况

如果只是判断 v == pre 的话,u  --- v之间就只能够访问到一条边,只有在题目说了两点之间不会有重边的时候才能这样

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

typedef long long LL;
const int maxn = 100005;

int first[maxn];
int ecnt,tot,cnt;
int low[maxn],iscut[maxn],dfn[maxn];
int vis[2*maxn],bri[maxn];
int N,M,T;

struct Edge{
    int u,v,nxt,id;
}e[2*maxn];

void Add_edges(int u,int v,int id){
    e[ecnt].v = v;
    e[ecnt].nxt = first[u];
    e[ecnt].id = id;
    first[u] = ecnt++;
}

void init(){
    ecnt = tot = cnt = 0;
    memset(first,-1,sizeof(first));
}

void Dfs(int p,int pre){
    low[p] = dfn[p] = ++tot;
    for(int i = first[p];~i;i = e[i].nxt){
        int v = e[i].v;
        if(vis[i]) continue;
        vis[i] = vis[i^1] = true;    
        if(!dfn[v]){
            Dfs(v,p);
            low[p] = min(low[p],low[v]);
            if(low[v] > dfn[p]) {
                bri[cnt++] = e[i].id;
            }
        }
        else low[p] = min(low[p],dfn[v]) ;
    }
}

void Tarjan(){
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(iscut,0,sizeof(iscut));
    memset(vis,0,sizeof(vis));
    Dfs(1,-1);
    
//    for(int i = 0;i < cnt;i++) printf("bri[%d] = %d\n",i,bri[i]);
    sort(bri,bri+cnt);
    printf("%d\n",cnt);
    
    for(int i = 0;i < cnt;i++){
            printf("%d",bri[i]);
            if(i!= cnt-1) printf(" ");
    }
    
    if(cnt) printf("\n");
    if(T) printf("\n");
    
}

int main(){
    scanf("%d",&T);
    while(T--){
        init();
        scanf("%d %d",&N,&M);
        for(int i = 1;i <= M;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            Add_edges(u,v,i);
            Add_edges(v,u,i);
        }
        Tarjan();
        
    }
    return 0;
}
View Code

 

(4)强连通分量

poj 3160

有找强连通的,还有缩点

缩点之后可以转化成DAG 上的动规做,还可以spfa来做

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;

const int maxn = 5005;
int n,m;
int first[maxn];
int sc[maxn],scn[maxn],low[maxn],pre[maxn];
int scnt,ecnt,dfs_clock;
int dp[maxn];

int first1[maxn];
int ecnt1;

int a[maxn];
int in[maxn];

struct Edge{
    int v,next;
}e[maxn*10];

Edge e1[maxn*10];

stack<int> S;

void init(){
    ecnt = ecnt1 = 0;
    memset(first,-1,sizeof(first));
    memset(first1,-1,sizeof(first1));
    memset(dp,0,sizeof(dp));
}

void addedges(int u,int v){
    e[ecnt].v = v;
    e[ecnt].next = first[u];
    first[u] = ecnt++;
}

void addedges1(int u,int v){
    e1[ecnt1].v = v;
    e1[ecnt1].next = first1[u];
    first1[u] = ecnt1++;
}

void dfs(int u){
    low[u] = pre[u] = ++dfs_clock;
    S.push(u);
    for(int i = first[u];~i;i = e[i].next){
        int v = e[i].v;
        if(!pre[v]){
            dfs(v);
            low[u] = min(low[u],low[v]);
        }
        else if(!sc[v]) low[u] = min(low[u],pre[v]);
    }
    if(pre[u] == low[u]){
        scnt++;
        for(;;){
            int x = S.top();S.pop();
            sc[x] = scnt;
            scn[scnt]+= a[x];
            if(x == u) break;
        }
    }
}

void find_scc(){
    while(!S.empty()) S.pop();
    scnt = dfs_clock = 0;
    memset(low,0,sizeof(low));memset(pre,0,sizeof(pre));
    memset(sc,0,sizeof(sc));memset(scn,0,sizeof(scn));
    
    for(int i = 1;i <= n;i++) if(!pre[i]) dfs(i);
}

int solve(int p){
    if(dp[p]) return dp[p];
    for(int i = first1[p];~i;i = e1[i].next){
        int v = e1[i].v;
        dp[p] = max(dp[p],solve(v));
    }
    return dp[p] = dp[p] + scn[p];
}

int main(){
    int T;
    while(scanf("%d %d",&n,&m) != EOF){
        init();
        for(int i = 1;i <= n;i++) {
            scanf("%d",&a[i]);
            if(a[i] < 0) a[i] = 0;
        }
        for(int i = 0;i < m;i++ ){
            int u,v;
            scanf("%d %d",&u,&v);u++;v++;
            addedges(u,v);
        }
        find_scc();
        
             memset(in,0,sizeof(in));
        for(int u = 1;u <= n;u++){
            for(int i = first[u];~i;i = e[i].next){
                int v = e[i].v;
                if(sc[u] != sc[v]) addedges1(sc[u],sc[v]),in[sc[v]]++;
            }
        }
        
        int ans = 0;
        for(int i = 1;i <= scnt;i++) {
            ans = max(ans,solve(i));
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 5005;
const int INF = 1000000005;
int n,m;
int first[maxn];
int sc[maxn],scn[maxn],low[maxn],pre[maxn];
int scnt,ecnt,dfs_clock;
int dp[maxn];

int du[maxn];
int dis[maxn];
int inq[maxn];

int first1[maxn];
int ecnt1;

struct Edge{
    int v,next;
}e[maxn*10];

Edge e1[maxn*10];

stack<int> S;
vector<int> g[maxn];
int val[maxn],a[maxn];

void init(){
    ecnt = ecnt1 = 0;
    memset(first,-1,sizeof(first));
    memset(val,0,sizeof(val));
    memset(du,0,sizeof(du));       
}

void addedges(int u,int v){
    e[ecnt].v = v;
    e[ecnt].next = first[u];
    first[u] = ecnt++;
}

void dfs(int u){
    low[u] = pre[u] = ++dfs_clock;
    S.push(u);
    for(int i = first[u];~i;i = e[i].next){
        int v = e[i].v;
        if(!pre[v]){
            dfs(v);
            low[u] = min(low[u],low[v]);
        }
        else if(!sc[v]) low[u] = min(low[u],pre[v]);
    }
    if(pre[u] == low[u]){
        scnt++;
        for(;;){
            int x = S.top();S.pop();
            sc[x] = scnt;
            val[scnt] += a[x];
            if(x == u) break;
        }
    }
}

void find_scc(){
    while(!S.empty()) S.pop();
    scnt = dfs_clock = 0;
    memset(low,0,sizeof(low));memset(pre,0,sizeof(pre));
    memset(sc,0,sizeof(sc));memset(scn,0,sizeof(scn));
    
    for(int i = 1;i <= n;i++) if(!pre[i]) dfs(i);
}


int spfa(){  
    memset(inq, 0, sizeof(inq));  
    queue<int>q;  
    g[0].clear();  
    q.push(0);  
    dis[0] = 0; val[0] = 0;  
    for(int i = 1; i <= scnt; i++){if(du[i] == 0)g[0].push_back(i); dis[i] = -INF;}  
    int ans = 0;  
    while(!q.empty()){  
        int u = q.front(); q.pop(); inq[u] = 0;  
        for(int i = 0; i < g[u].size(); i++){  
            int v = g[u][i];  
            if(dis[v] < dis[u] + val[v]){  
                dis[v] = dis[u] + val[v];  
                ans = max(ans, dis[v]);  
                if(inq[v] == 0)inq[v] = 1, q.push(v);  
            }  
        }  
    }  
    return ans;  
}  

int main(){
    while(scanf("%d %d",&n,&m) != EOF){
        init();
        for(int i = 1;i <= n;i++) {
            scanf("%d",&a[i]);
            if(a[i] < 0) a[i] = 0;
        }      
        for(int i = 0;i < m;i++ ){
            int u,v;
            scanf("%d %d",&u,&v);u++;v++;
            addedges(u,v);
        }
        find_scc();
        for(int i = 1;i <= scnt;i++) g[i].clear();
    
        for(int u = 1;u <= n;u++){
            for(int i = first[u];~i;i = e[i].next){
                int v = e[i].v;
                if(sc[u] != sc[v]) g[sc[u]].push_back(sc[v]),du[sc[v]]++;
            }
        }
        printf("%d\n",spfa());
    }
    return 0;
}
View Code

 

(5)二分图最大匹配

poj 1274

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

const int maxn = 1005;
int n,m;
int used[maxn],mat[maxn];
vector<int> g[maxn];

void init(){
    memset(mat,0,sizeof(mat));
    for(int i = 1;i <= n;i++) g[i].clear();
}

bool find(int p){
    for(int i = 0;i < g[p].size();i++){
        int v = g[p][i];
        if(!used[v]){
            used[v] = 1;
            if(!mat[v] || find(mat[v])){
                mat[v] = p;
                return true;
            }
        }
    }
    return false;
}

int Hungary(){
    int res = 0;
    for(int i = 1;i <= n;i++) {
        memset(used,0,sizeof(used));
        if(find(i)) res++;
    }
    return res;
}

int main(){
    while(scanf("%d %d",&n,&m) != EOF){
        init();
        for(int i = 1;i <= n;i++){
            int a,u;
            scanf("%d",&a);
            for(int j = 1;j <= a;j++){
                scanf("%d",&u);
                g[i].push_back(u);
            }
        }
        printf("%d\n",Hungary());
    }
    return 0;
}
View Code

 

(6)二分图最大权匹配

hdu 1533

如果是求最小权匹配的话,边权改成负的就可以了

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int M = 210;

int n,nx,ny,m,r,c;
int link[M],lx[M],ly[M],slack[M];  //lx,ly为顶标, slack为可改进量 
int visx[M],visy[M],w[M][M];

int Dfs(int x){
    visx[x] = 1;
    for (int y = 1;y <= ny;y ++){
        if (visy[y])
            continue;
        int t = lx[x] + ly[y] - w[x][y];
        if (t == 0){
            visy[y] = 1;
            if (link[y] == -1 || Dfs(link[y])){
                link[y] = x;
                return 1;
            }
        }
        else if (slack[y] > t)  
            slack[y] = t;
    }
    return 0;
}

int KM(){
    int i,j;
    memset (link,-1,sizeof(link));
    memset (ly,0,sizeof(ly));           //ly 初始化为 0 
    for (i = 1;i <= nx;i ++)            //lx初始化为与它关联边中最大的
        for (j = 1,lx[i] = -INF;j <= ny;j ++)
            if (w[i][j] > lx[i])
                lx[i] = w[i][j];
    for (int x = 1;x <= nx;x ++){
        for (i = 1;i <= ny;i ++)
            slack[i] = INF;
        while (1){
            memset (visx,0,sizeof(visx));
            memset (visy,0,sizeof(visy));
            if (Dfs(x))     //如果找到增广路,说明这个点增广完成,跳出,进入下一个点的增广 
                break;      //如果失败的话,就要修改顶标,
                            //方法是将在增广过程中遇到的X的顶标全部减去d,将遇到的Y的顶标全部加上d  

            int d = INF;
            for (i = 1;i <= ny;i ++)
                if (!visy[i]&&d > slack[i])
                    d = slack[i];
            for (i = 1;i <= nx;i ++)
                if (visx[i])
                    lx[i] -= d;
            for (i = 1;i <= ny;i ++)  
                if (visy[i])
                    ly[i] += d;
                else
                    slack[i] -= d;
        }
    }
    int res = 0;
    for (i = 1;i <= ny;i ++)
        if (link[i] > -1)
            res += w[link[i]][i];
    return res;
}

char g[M][M];

struct node{
    int x,y;
}house[M],men[M];

int cal(int x,int y){
    return abs(house[x].x - men[y].x) + abs(house[x].y - men[y].y);
}

int main(){
    while(scanf("%d %d",&r,&c) != EOF && r && c){
        nx = ny = 0;
        for(int i = 1;i <= r;i++) scanf("%s",g[i]+1);
        
        for(int i = 1;i <= r;i++){
            for(int j = 1;j <= c;j++){
                if(g[i][j] == 'H') house[++nx].x = i,house[nx].y = j;
                if(g[i][j] == 'm') men[++ny].x = i,men[ny].y = j;
            }
        }
        
        for(int i = 1;i <= nx;i++){
            for(int j = 1;j <= ny;j++){
                w[i][j] = -cal(i,j);
            }
        }
        printf("%d\n",-KM());
    }
    return 0;
}
View Code

 

(7) LCA

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #include <queue>
 10 #include <string>
 11 #include <iostream>
 12 #include <algorithm>
 13 using namespace std;
 14 
 15 #define MEM(a,b) memset(a,b,sizeof(a))
 16 #define REP(i,n) for(int i=1;i<=(n);++i)
 17 #define REV(i,n) for(int i=(n);i>=1;--i)
 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
 20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
 21 #define MP(a,b) make_pair(a,b)
 22 
 23 typedef long long ll;
 24 typedef pair<int,int> pii;
 25 const int INF = (1 << 30) - 1;
 26 const int MAXN = 400010;
 27 const int MAX_LOG = 32;
 28 
 29 int T,n,m,q;
 30 int first[MAXN],ecnt;
 31 int fa[MAX_LOG][MAXN],dep[MAXN];
 32 ll dis[MAXN];
 33 
 34 int sx,sy,sz;
 35 
 36 struct edge{
 37     int v,next,w;
 38 }e[MAXN << 1];
 39 
 40 void Add_edge(int u,int v,int c){
 41     e[++ecnt].next = first[u];
 42     e[ecnt].v = v;
 43     e[ecnt].w = c;
 44     first[u] = ecnt;
 45 }
 46 
 47 void Dfs(int p,int pre,int d){
 48     fa[0][p] = pre;
 49     dep[p] = d;
 50     for(int i = first[p]; ~i; i = e[i].next){
 51         int v = e[i].v;
 52         if(v == pre) continue;
 53         dis[v] = dis[p] + e[i].w;
 54         Dfs(v,p,d + 1);
 55     }
 56 }
 57     
 58 void Pre(){
 59     dis[1] = 0;
 60     Dfs(1,-1,0);
 61     for(int k = 0; k + 1 < MAX_LOG; ++k){
 62         for(int v = 1; v <= n; ++v){
 63             if(fa[k][v] < 0) fa[k + 1][v] = -1;
 64             else fa[k + 1][v] = fa[k][fa[k][v]];
 65         }
 66     }
 67 }
 68 
 69 int Lca(int u,int v){
 70     if(dep[u] > dep[v]) swap(u,v);
 71     for(int k = MAX_LOG - 1; k >= 0; --k){
 72         if((dep[v] - dep[u]) & (1 << k))
 73             v = fa[k][v];
 74     }
 75     if(u == v) return u; //u为v的根
 76     for(int k = MAX_LOG - 1; k >= 0; --k){
 77         if(fa[k][u] != fa[k][v]){
 78             u = fa[k][u];
 79             v = fa[k][v];
 80         }
 81     }
 82     return fa[0][u]; //u离lca只差一步
 83 }
 84 
 85 void solve(){
 86     int lcaa = Lca(sx,sy);
 87     for(int i = 1;i <= q;i++){
 88         int x,y;
 89         scanf("%d %d",&x,&y);
 90         int lca = Lca(x,y);
 91         int l = dis[x] + dis[y] - 2*dis[lca];
 92         
 93         int lb = sz + (dis[x] + dis[sx] - 2*dis[Lca(x,sx)]) + (dis[sy]+dis[y]-2*dis[Lca(sy,y)]);
 94         int ub = sz + (dis[x] + dis[sy] - 2*dis[Lca(x,sy)]) + (dis[sx]+dis[y]-2*dis[Lca(sx,y)]);
 95         
 96         int r = min(l,min(lb,ub));
 97         printf("%d\n",l-r);
 98     }
 99 }
100 
101 int main(){
102     int a,b,c;
103     scanf("%d",&T);
104     int kase = 0;
105     while(T--){
106         MEM(first,-1);
107         ecnt = 0;
108         scanf("%d%d",&n,&q);
109         REP(i,n - 1){
110             scanf("%d%d%d",&a,&b,&c);
111             Add_edge(a,b,c);
112             Add_edge(b,a,c);
113         }
114         
115         scanf("%d %d %d",&sx,&sy,&sz);
116         
117         Pre();
118         
119         printf("Case #%d:\n",++kase);
120         
121         solve();
122     }
123     return 0;
124 }
View Code


再补一个,里面的 Up(d,u)是算从u节点向上跳 d 到达的节点

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

const int INF = (1<<30)-1;
const int maxn = 400005;
const int MAX_LOG = 20;

int n,m;
int first[maxn],ecnt;
int fa[MAX_LOG][maxn],dep[maxn];
int dp[maxn],vis[maxn];
int sz[maxn];

struct Edge{
    int u,v,next,w;
};

Edge e[10*maxn],ea[10*maxn];

void init(){
    ecnt  = 0;
    memset(first,-1,sizeof(first));
}

void Add_edge(int u,int v){
    e[ecnt].u = u;
    e[ecnt].v = v;
    e[ecnt].next = first[u];
    first[u] = ecnt++;
}

void Dfs(int p,int pre,int d){
    fa[0][p] = pre;
    dep[p] = d;
    sz[p] = 1;
    for(int i = first[p];~i;i = e[i].next){
        int v = e[i].v;
        if(v == pre) continue;
        Dfs(v,p,d+1);
        sz[p] += sz[v];
    }
}

void Pre(){
    Dfs(1,-1,0);
    for(int k = 0;k+1 < MAX_LOG;++k){
        for(int v = 1;v <= n;v++){
            if(fa[k][v] < 0) fa[k+1][v] = -1;
            else fa[k+1][v] = fa[k][fa[k][v]];
        }
    }
}

int Lca(int u,int v){
    if(dep[u] > dep[v]) swap(u,v);
    for(int k = MAX_LOG-1;k >= 0;--k){
        if(dep[v]-dep[u] & (1<<k))
        v = fa[k][v];
    }
    if(u == v) return u;
    for(int k = MAX_LOG-1;k >= 0;--k){
        if(fa[k][u] != fa[k][v]){
            u = fa[k][u];
            v = fa[k][v];
        }
    }
    return fa[0][u];
}

int Up(int d,int u){
    for(int k = MAX_LOG-1;k >= 0;k--){
        if(d & (1<<k)) u = fa[k][u];
    }
    return u;
}

void solve(int u,int v){
    if(u == v){
        printf("%d\n",n);
        return;
    }
    int lca = Lca(u,v);
    //printf("u = %d  v = %d  lca = %d\n",u,v,lca);
    
    int l = dep[u] + dep[v]-2*dep[lca];
        if(l%2){
            printf("0\n");
            return;
        }
    
    if((u == lca && v != lca) || (u != lca && v == lca)){
        int x = 0;
        if(u == lca) x = v;
        else x = u;
        
        int y = Up(l/2,x);
        int z = Up(l/2-1,x);
    //    printf("x = %d  y = %d lca = %d\n",x,y,lca);
        int res = sz[y]-sz[z];
        printf("%d\n",res);
    }
    
    if(u != lca && v != lca){
        int l = dep[u] - dep[lca];
        int r = dep[v] - dep[lca];
    //    printf("u = %d v = %d  l = %d r = %d\n",u,v,l,r);
        if(l == r){    
            int y = Up(l-1,u);
            int z = Up(r-1,v);
    //        printf("===l = %d  r = %d y = %d  z = %d\n",l,r,y,z);
            int res = n-sz[y]-sz[z];
            printf("%d\n",res);
        }
        else{
            if(dep[u] > dep[v]) swap(u,v);
            int x = v;
            int y = Up((l+r)/2,x);
            int z = Up((l+r)/2-1,x);
    //        printf("---x = %d  y = %d  z = %d\n",x,y,z);
            int res = sz[y]-sz[z];
            printf("%d\n",res);
        }
    }    
}

int main(){
    while(scanf("%d",&n) != EOF){
        init();
        for(int i = 1;i <= n-1;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            Add_edge(u,v);
            Add_edge(v,u);
        }
        memset(sz,0,sizeof(sz));
        Pre();
        scanf("%d",&m);
        for(int i = 1;i <= m;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            solve(u,v);
        }
    }
    return 0;
}
View Code

 

(8) 最大流

1.dinic

hdu 3549

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

const int maxn = 10005;
const int INF = (1 << 30) - 1;

struct Edge{
    int v,next,c;
}e[maxn];

int st,ed,lev[maxn],first[maxn],now[maxn],ecnt;
int n,m;

void init(int a,int b){
    st = a; ed = b;
    memset(first,-1,sizeof(first));
    ecnt = 0;
}

void addedges(int u,int v,int c){
    e[ecnt].next = first[u];
    e[ecnt].v = v;
    e[ecnt].c = c;
    first[u] = ecnt++;
    
    e[ecnt].next = first[v];
    e[ecnt].v = u;
    e[ecnt].c = 0;
    first[v] = ecnt++;
}

bool bfs(){
    queue<int> q;
    while(!q.empty()) q.pop();
    q.push(st);
    memset(lev,-1,sizeof(lev));
    lev[st] = 0;
    while(!q.empty()){
        int x = q.front();q.pop();
        for(int i = first[x];~i;i = e[i].next){
            int v = e[i].v;
            if(lev[v] < 0 && e[i].c > 0){
                lev[v] = lev[x] + 1;
                q.push(v);
            }
        }
    }
    return lev[ed] != -1;
}

int dfs(int p,int minf){
    if(p == ed || minf == 0) return minf;
    for(int &i = now[p];~i;i = e[i].next){
        int v = e[i].v;
        if(lev[v] == lev[p] + 1 && e[i].c > 0){
            int d = dfs(v,min(e[i].c,minf));
            if(d > 0){
                e[i].c -= d;
                e[i^1].c += d;
                return d;
            }
        }
    }
    return 0;
}

int dinic(){
    int max_flow = 0,p1;
    while(bfs()){
        memcpy(now,first,sizeof(first));
        while((p1 = dfs(st,INF)) > 0)
        max_flow += p1;
    }
    return max_flow;
}

int main(){
    int T;
    int kase = 0;
    scanf("%d",&T);
    while(T--){        
        scanf("%d %d",&n,&m);
        init(1,n);
        for(int i = 0;i < m;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            addedges(a,b,c);
        }
        printf("Case %d: %d\n",++kase,dinic());
    }
    return 0;
}
View Code

 2.ISAP

hdu 1532

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 1005;
const int INF = (1 << 30) - 1;

struct Edge{
    int from,to,cap,flow;
};

vector<Edge> edges;

int source;         // 源点
int sink;           // 汇点
int p[maxn];   // 可增广路上的上一条弧的编号
int num[maxn]; // 和 t 的最短距离等于 i 的节点数量
int cur[maxn]; // 当前弧下标
int d[maxn];   // 残量网络中节点 i 到汇点 t 的最短距离
bool visited[maxn];

int num_nodes;

vector<int> G[maxn];

// 预处理, 反向 BFS 构造 d 数组
bool bfs()
{
    memset(visited, 0, sizeof(visited));
    queue<int> Q;
    Q.push(sink);
    visited[sink] = 1;
    d[sink] = 0;
    while (!Q.empty()) {
        int u = Q.front();
        Q.pop();
        for ( int i = 0;i < G[u].size();i++) {
            Edge &e = edges[G[u][i]^1];
            if (!visited[e.from] && e.cap> e.flow) {
                visited[e.from] = true;
                d[e.from] = d[u] + 1;
                Q.push(e.from);
            }
        }
    }
    return visited[source];
}

// 增广
int augment()
{
    int u = sink, df = INF;
    // 从汇点到源点通过 p 追踪增广路径, df 为一路上最小的残量
    while (u != source) {
        Edge &e = edges[p[u]];
        df = min(df, e.cap - e.flow);
        u = edges[p[u]].from;
    }
    u = sink;
    // 从汇点到源点更新流量
    while (u != source) {
        edges[p[u]].flow += df;
        edges[p[u]^1].flow -= df;
        u = edges[p[u]].from;
    }
    return df;
}

int max_flow()
{
    int flow = 0;
    bfs();
    memset(num, 0, sizeof(num));
    for (int i = 0; i < num_nodes; i++) num[d[i]]++;
    int u = source;
    memset(cur, 0, sizeof(cur));
    while (d[source] < num_nodes) {
        if (u == sink) {
            flow += augment();
            u = source;
        }
        bool advanced = false;
        for (int i = cur[u]; i < G[u].size(); i++) { 
            Edge& e = edges[G[u][i]];
            if (e.cap > e.flow && d[u] == d[e.to] + 1) {
                advanced = true;
                p[e.to] = G[u][i];
                cur[u] = i;
                u = e.to;
                break;
            }
        }
        if (!advanced) { // retreat
            int m = num_nodes - 1;
            for ( int i = 0;i < G[u].size();i++)
                if (edges[G[u][i]].cap > edges[G[u][i]].flow)
                    m = min(m, d[edges[G[u][i]].to]);
            if (--num[d[u]] == 0) break; // gap 优化
            num[d[u] = m+1]++;
            cur[u] = 0;
            if (u != source)
                u = edges[p[u]].from;
        }
    }
    return flow;
}

void addedges(int from,int to,int cap){
    edges.push_back((Edge){from,to,cap,0});
    edges.push_back((Edge){to,from,0,0});
    int m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
}

void init(){
    edges.clear();
    for(int i = 0;i < num_nodes;i++) G[i].clear();
}

int main(){
    int m;
    while(scanf("%d %d ",&m,&num_nodes) != EOF){
        init();
        source = 0; sink = num_nodes-1;
        for(int i = 0;i < m;i++){
            int u,v,c;
            scanf("%d %d %d",&u,&v,&c);u--;v--;
            addedges(u,v,c);
        }
        int res = max_flow();
        printf("%d\n",res);
    }
    return 0;
}
View Code

 (9) 最小费用最大流

poj 2135

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
using namespace std;

typedef long long LL;
const int maxn = 5000;
const int INF = (1 << 30) - 1;
 
int first[maxn],vis[maxn],dis[maxn],pos[maxn],ecnt,size;

struct Edge{
    int v,next,cap,cost;
} e[10*maxn];

void init(){
    ecnt = 0;
    memset(first,-1,sizeof(first));
}
  
void add_edge(int u,int v,int cap,int cost){
    e[ecnt].v = v;
    e[ecnt].cap = cap;
    e[ecnt].cost = cost;
    e[ecnt].next = first[u];
    first[u] = ecnt++;
    
    e[ecnt].v = u;
    e[ecnt].cap = 0;
    e[ecnt].cost = -cost;
    e[ecnt].next = first[v];
    first[v] = ecnt++;
}
  
bool SPFA(int s, int t)
{
    int u,v,i;
    queue <int> q;
    memset(vis,0,sizeof(vis));
    for(i= 0;i <= size;i++) dis[i]=INF;
    
    dis[s]=0;
    vis[s]=1;
    q.push(s);
    
    while(!q.empty()){
        u=q.front(); q.pop(); vis[u]=0;
        for (i = first[u]; ~i;i = e[i].next){
               v=e[i].v; 
               if(e[i].cap > 0&& dis[u]+e[i].cost < dis[v]){
                  dis[v]=dis[u]+e[i].cost;
                  pos[v]=i;
                  if(!vis[v]){
                     vis[v]=1;
                     q.push(v);
                  }
               }
          }
    }
    return dis[t] != INF;
}

LL MCMF(int s,int t)
{
    int i;
    LL cost=0,flow=0;
    while(SPFA(s,t)){
        int d=INF;
        for (i = t;i != s;i = e[pos[i]^1].v){
            d = min(d,e[pos[i]].cap);
        }
        for(i = t;i != s;i = e[pos[i]^1].v){
            e[pos[i]].cap -= d;
            e[pos[i]^1].cap += d;
        }
        flow += d;
        cost += dis[t]*d;
    }
    return cost;
}


int main(){
    int n,m;
    while(scanf("%d %d",&n,&m) != EOF){
        init();
        size = n+1;
        add_edge(0,1,2,0); add_edge(1,0,2,0);
        add_edge(n+1,n,2,0);add_edge(n,n+1,2,0);
        
        for(int i = 0;i < m;i++){
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            add_edge(u,v,1,w);
            add_edge(v,u,1,w);
        }
        printf("%I64d\n",MCMF(0,n+1));
    }
    return 0;
}
View Code

又抄了一个

 1 struct edge{
 2     int v,next,cost,cp;
 3 };
 4 
 5 struct MCMF{
 6     edge e[MAXM];
 7     int sou,sin;
 8     int first[MAXN],ecnt;
 9     int dis[MAXN];
10     int prev[MAXN],pree[MAXN],inq[MAXN];
11     void init(int a,int b){
12         sou = a;
13         sin = b;
14         memset(first,-1,sizeof(first));
15         ecnt = 0;
16     }
17     void add_edge(int u,int v,int cap,int fee){
18         e[ecnt].next = first[u];
19         e[ecnt].v = v;
20         e[ecnt].cp = cap;
21         e[ecnt].cost = fee;
22         first[u] = ecnt++;
23 
24         e[ecnt].next = first[v];
25         e[ecnt].v = u;
26         e[ecnt].cp = 0;
27         e[ecnt].cost = -fee;
28         first[v] = ecnt++;
29     }
30     bool Spfa(){
31         fill(dis,dis + MAXN,INF);
32         dis[sou] = 0;
33         MEM(prev,-1),MEM(inq,0);
34         queue<int> Q;
35         Q.push(sou);
36         while(!Q.empty()){
37             int x = Q.front(); Q.pop();
38             inq[x] = 0;
39             for(int i = first[x]; ~i; i = e[i].next){
40                 if(e[i].cp <= 0) continue;
41                 int v = e[i].v;
42                 if(dis[x] + e[i].cost < dis[v]){
43                     dis[v] = dis[x] + e[i].cost;
44                     prev[v] = x;
45                     pree[v] = i;
46                     if(inq[v] == 0){
47                         inq[v] = 1;
48                         Q.push(v);
49                     }
50                 }
51             }
52         }
53         if(dis[sin] > 0) return false;
54         return prev[sin] != -1;
55     }
56     int Solve(){
57         //int sumf = 0;
58         int min_cost = 0;
59         while(Spfa()){
60             int minf = INF;
61             for(int i = sin; i != sou; i = prev[i]){
62                 int id = pree[i];
63                 minf = min(minf,e[id].cp);
64             }
65             for(int i = sin; i != sou; i = prev[i]){
66                 int id = pree[i];
67                 e[id].cp -= minf;
68                 e[id ^ 1].cp += minf;
69             }
70             //sumf += minf;
71             min_cost += dis[sin] * minf;
72         }
73         //printf("flow : %d\n",sumf);
74         return min_cost;
75     }
76 }MC;
View Code

 

 

(10) 生成树计数

/*
它的度数矩阵记为 d[][]
 
当 i = j 的时候,d[i][j] 为 vi的度数
 
当 i != j 的时候,d[i][j]为0
 
它的邻接矩阵记为 a[][]
 
当i = j 的时候, a[i][j] = 0
 
当 i!= j的时候,如果i到j有边的话,a[i][j] = a[j][i] = 1
 
它的Kirchhoff矩阵等于 == d - a
 
然后无向图的生成树的个数为 它的Kirchhoff矩阵的任意 n-1 阶主子式的行列式绝对值

*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

typedef long long LL;
const int MAXN = 15;
LL g[MAXN][MAXN];
int n,m;
int d[MAXN];

LL Det(LL A[MAXN][MAXN],int n){ 
    LL res = 1;
    for(int i = 1; i <= n; ++i){
        for(int j = i + 1; j <= n; ++j){
            while(A[j][i]){
                LL t = A[i][i] / A[j][i];
                for(int k = i; k <= n; ++k)
                    A[i][k] = (A[i][k] - A[j][k] * t);
                for(int k = i; k <= n; ++k)
                    swap(A[i][k],A[j][k]);
                res = -res; //行列式换行,值取反
            }
        }
        if(!A[i][i]) return 0;
        res = res * A[i][i] ;
    }
    if(res < 0) res = -res;
    return res;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        memset(g,0,sizeof(g));
        memset(d,0,sizeof(d));
        scanf("%d %d",&n,&m);
        for(int i = 1;i <= m;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            g[u][v] = g[v][u] = -1;
            d[u]++;d[v]++;
        }
        for(int i = 1;i <= n;i++) g[i][i] = d[i];//g为原图的Kirchhoff矩阵 
        printf("%lld\n",Det(g,n-1));//对矩阵g求一次n-1阶主子式的行列式绝对值 
    }
    return 0;
}
View Code

 

数论

(1) 矩阵快速幂

hdu 4990

转移矩阵记得初始化

答案矩阵记得最开始弄成单位矩阵

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

//wei ziji jiayou >_< 99
typedef long long LL;
int n;
int mod;

struct Mx{
    int a[3][3];
    void clear(){
        for(int i = 0;i < 3;i++)
         for(int j = 0;j < 3;j++) a[i][j] = 0;
    }
    
    void stand(){
        for(int i = 0;i < 3;i++){
            for(int j = 0;j < 3;j++){
                if(i == j) a[i][j] = 1;
                else a[i][j] = 0;
            }
        }
    }
    
    Mx operator * (const Mx &b) const {
        Mx c;
        c.clear();
        for(int k = 0;k < 3;k++)
         for(int i = 0;i < 3;i++)
          for(int j = 0;j < 3;j++){
              c.a[i][j] = (c.a[i][j] + (LL)a[i][k] * b.a[k][j]) % mod;
          }
          return c;
    }

};

LL Mx_pow(int n){
    Mx y,a;
    y.stand();
    a.a[0][0] = 1;a.a[0][1] = 2;a.a[0][2] = 1;
    a.a[1][0] = 1;a.a[1][1] = 0;a.a[1][2] = 0;
    a.a[2][0] = 0;a.a[2][1] = 0;a.a[2][2] = 1;
    
    while(n){
        if(n&1) y = y*a;
        if(n >>= 1) a = a*a;
    }
    
//    for(int i = 0;i < 3;i++){
//        for(int j = 0;j < 3;j++) printf("%d ",y.a[i][j]);
//        printf("\n");
//    }
    
    return y.a[0][0]%mod;
}

int main(){
    while(scanf("%d %d",&n,&mod) != EOF){
        int ans = Mx_pow(n);
        if(n%2 == 0) ans--;
        printf("%d\n",ans % mod);
    }
    return 0;
}
View Code

(2) 算组合数

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
const int MAXN = 2000010;
const ll mod = 1e9 + 7;

int N;
ll fac[MAXN + 10],afac[MAXN + 10];

ll Q_pow(ll x,ll y){
    ll res = 1;
    x %= mod;
    while(y){
        if(y & 1) res = res * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return res;
}

void Pre(){
    fac[0] = 1;
    for(int i = 1; i <= MAXN; ++i) fac[i] = fac[i - 1] * (ll)i % mod;
    afac[MAXN] = Q_pow(fac[MAXN],mod - 2);
    for(int i = MAXN; i >= 1; --i) afac[i - 1] = afac[i] * i % mod;
}

ll C(ll n,ll m){
    if(m > n) return 0;
    return fac[n] * afac[n - m] % mod * afac[m] % mod;
}

int main(){
    Pre();
    scanf("%d",&N);
    ll ans = Q_pow(2,N+1)-1;
    ll cur = Q_pow(2,N);
    ll tmp = cur;
    for(int i = N+1;i <= 2*N;i++){
        ll shao = 2LL*((C(i-1,N) - C(i-2,N) + mod) % mod) %mod;
    //    printf("shao = %I64d\n",shao);
        tmp = (tmp-shao + mod)%mod;
         cur = cur + tmp;
         ans = (ans + cur) %mod;
         tmp = 2LL*tmp%mod;
    }
    printf("%I64d\n",ans);
    return 0;
}
View Code

 (3)筛一个数由哪些素数组成

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;

typedef long long LL;
const int maxn = 100005;
int dp[maxn];
int Max[maxn];
vector<int> p;

int vis[maxn];
int T,a[105];
int cnt[maxn];
set<long long > s;
LL n;

void solve( long long  x){
    LL y = x;
   // printf("y = %I64d\n",y);
    for(long long  j = 2;1LL*j*j <= y;j++){
        if(y%j == 0){
        //    printf("j = %I64d\n",j);
            while(y%j == 0){
                s.insert(j);
                y = y/j;
            }
        }        
    }
    if(y > 1) s.insert(y);
    
   // for(set<long long >::iterator it = s.begin();it != s.end();++it){
    //    printf("*it = %d\n",*it);
    //}
    
}

void work(){
    if(n == 1){
        puts("1");
        return;
    }
    if(s.size() < 2){
        printf("%I64d\n",*s.begin());
        return;
    }
    LL res = 1;
    for(set<long long >::iterator it = s.begin();it != s.end();++it){
        res = res*(*it);
    }
    printf("%I64d\n",res);
}

int main(){
    while(scanf("%I64d",&n) != EOF){
        s.clear();
        solve(n);
        work();
    }
    return 0;
}
View Code

 

你可能感兴趣的:(整理---------)