码迷,mamicode.com
首页 > 其他好文 > 详细

《挑战程序设计竞赛》2.5 它们其实都是图

时间:2016-07-13 13:51:06      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:

poj 2139 Six Degrees of Cowvin Baconfloyd的模板题。

建图的时候记得i==j的时候ma[i][j]=0;其他情况是inf

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int N,M;
 6 const int maxn=305;
 7 const int INF=0x3f3f3f3f;
 8 int d[maxn][maxn],a[maxn];
 9 void init()
10 {
11     for(int i=0;i<maxn;i++)
12         for(int j=0;j<maxn;j++)
13             d[i][j] = (i==j)?0:INF;
14 }
15 
16 void floyd()
17 {
18     for(int k=1;k<=N;k++)
19         for(int i=1;i<=N;i++)
20             for(int j=1;j<=N;j++)
21                 d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
22 }
23 
24 int main()
25 {
26     while(cin>>N>>M)
27     {
28         init();
29         //输入数据并建图
30         for(int i=0;i<M;i++)
31         {
32             int n,t;
33             cin>>n;
34             for(int j=0;j<n;j++)
35                 cin>>a[j];
36             for(int j=0;j<n;j++)
37                 for(int k=0;k<j;k++)
38                     d[ a[j] ][ a[k] ]=d[ a[k] ][ a[j] ]=1;
39         }
40 
41         floyd();
42 
43         int minn=INF;
44         for(int i=1;i<=N;i++)
45         {
46             int tot=0;
47             for(int j=1;j<=N;j++)
48             {
49                 if(i!=j)
50                     tot+=d[i][j];
51             }
52             minn=min(minn,100*tot/(N-1));
53         }
54         cout<<minn<<endl;
55     }
56 
57     return 0;
58 }

 

poj 3259 Wormholes

题目的意思其实就是找负环。不懂的可以翻翻书,负环的时候没有最短路,因为它可以通过负环不断的变小。

这里用的是spfa判负环。模板题!熟悉算法,了解模板,写出自己的模板来。可以熟悉一下spfa。

 1 #include <cstdio>
 2 #include <vector>
 3 #include <queue>
 4 #include <cstring>
 5 using namespace std;
 6 int n,m,w;
 7 const int maxv=500+5;
 8 const int INF=0x3f3f3f3f;
 9 int vis[maxv],cnt[maxv],dis[maxv];
10 
11 struct Node
12 {
13     int to,weight;
14     Node(int too,int wei):to(too),weight(wei){}
15 };
16 vector<Node>G[maxv];
17 void ma_init()
18 {
19     scanf("%d%d%d",&n,&m,&w);
20     for(int i=1;i<=n;i++)//vector要记得重置
21         G[i].clear();
22     int s,e,t;
23     for(int i=0;i<m;i++)
24     {
25         scanf("%d%d%d",&s,&e,&t);
26         G[s].push_back( Node(e,t));//因为这个边是双向的,所以两边都要压进去。
27         G[e].push_back( Node(s,t));
28     }
29     for(int i=0;i<w;i++)
30     {
31         scanf("%d%d%d",&s,&e,&t);
32         G[s].push_back( Node(e,-t));//虫洞是单向的 且是负值
33     }
34 }
35 
36 bool spfa(int s)
37 {
38     memset(vis,0,sizeof(vis));
39     memset(cnt,0,sizeof(cnt));
40     for(int i=1;i<=n;i++)//初始化distant数组
41         dis[i]=INF;
42     //进队之前的初始化
43     queue<int>que;
44     dis[s]=0;
45     que.push(s);
46     vis[s]=cnt[s]=1;
47 
48     while(!que.empty())
49     {
50         //取出队列中队首的顶点的编号fv
51         int fv=que.front();
52 
53         for(int i=0;i<G[fv].size();i++)//对顶点fv,的所有相连的边进行一次遍历。
54         {
55             //G[fv][[i]这条边的from为顶点fv,它的to和weight分别用fto和fwei取出来
56             int fto=G[fv][i].to;
57             int fwei=G[fv][i].weight;
58             //进行更新
59             if(dis[fto] > dis[fv]+fwei)
60             {
61                 dis[fto]=dis[fv]+fwei;
62                 //若顶点fto此时不在队列中
63                 if(vis[fto] == 0)
64                 {//则压进栈中,并更新一系列数据
65                     que.push(fto);
66                     vis[fto]=1;
67                     cnt[fto]++;
68                     if(cnt[fto]>n-1) //如果有一个顶点进队了n次,则存在负环
69                         return true;
70                 }
71             }
72         }
73         que.pop();
74         vis[fv]=0;//弹出之后消除标记
75     }
76     return false;
77 
78 }
79 int main()
80 {
81     int T;
82     scanf("%d",&T);
83     while(T--)
84     {
85         ma_init();
86         if(spfa(1) || dis[1]<0 )
87             printf("YES\n");
88         else
89             printf("NO\n");
90     }
91     return 0;
92 }

 

poj 3268 Silver Cow Party

求一个点到其他各个点的最短路,容易吧。dijkstra或者spfa都能完成,那这道题聚会完回家的计算已经解决了,那去聚会的计算怎么办呢。一个反向的思维。就是说把边反向,那么又是一个从一个点到其他各个点的最短路的问题了。所以两次最短路模板一套就解决了。

其实这也是个模板,dijkstra的模板题。

  1 #include <cstdio>
  2 #include <vector>
  3 #include <queue>
  4 using namespace std;
  5 const int maxv=1000+5;
  6 const int INF=0x3f3f3f3f;
  7 typedef pair<int,int>P;
  8 int d[maxv],ans[maxv];
  9 int n,m,x;
 10 struct edge
 11 {
 12     int to,cost;
 13     edge(int t,int c):to(t),cost(c){}
 14     bool operator <(const edge& a)const
 15     {
 16         if(cost!=a.cost) return cost > a.cost;
 17         else return to < a.to;
 18     }
 19 };
 20 
 21 vector<edge>G1[maxv];
 22 vector<edge>G2[maxv];
 23 void ma_init()
 24 {
 25     for(int i=0;i<maxv;i++)
 26     {
 27         G1[i].clear();
 28         G2[i].clear();
 29         ans[i]=0;
 30     }
 31 }
 32 
 33 void dijkstra_g1(int s)
 34 {
 35     for(int i=0;i<maxv;i++)
 36         d[i]=INF;
 37 
 38     priority_queue<P>que;
 39     d[s]=0;
 40     que.push(P(d[s],s));
 41     while(!que.empty())
 42     {
 43         P p = que.top();que.pop();
 44         int v=p.second;
 45         if(d[v] < p.first) continue;
 46         for(int i=0;i<G1[v].size();i++)
 47         {
 48             edge e = G1[v][i];
 49             if(d[e.to] > d[v] + e.cost )
 50             {
 51                 d[e.to] = d[v] + e.cost;
 52                 que.push(P(d[e.to],e.to));
 53             }
 54         }
 55     }
 56 
 57 
 58     for(int i=1;i<=n;i++)
 59         ans[i]+=d[i];
 60 
 61 }
 62 
 63 void dijkstra_g2(int s)
 64 {
 65     for(int i=0;i<maxv;i++)
 66         d[i]=INF;
 67 
 68     priority_queue<P>que;
 69     d[s]=0;
 70     que.push(P(d[s],s));
 71     while(!que.empty())
 72     {
 73         P p = que.top();que.pop();
 74         int v=p.second;
 75         if(d[v] < p.first) continue;
 76         for(int i=0;i<G2[v].size();i++)
 77         {
 78             edge e = G2[v][i];
 79             if(d[e.to] > d[v] + e.cost )
 80             {
 81                 d[e.to] = d[v] + e.cost;
 82                 que.push(P(d[e.to],e.to));
 83             }
 84         }
 85     }
 86 
 87 
 88     for(int i=1;i<=n;i++)
 89         ans[i]+=d[i];
 90 
 91 }
 92 
 93 int main()
 94 {
 95     while(~scanf("%d%d%d",&n,&m,&x))
 96     {
 97         //一共有n只牛,m条路,在x牛处举行party
 98         ma_init();
 99         for(int i=0;i<m;i++)
100         {
101             int from,to,cost;
102             scanf("%d%d%d",&from,&to,&cost);
103             G1[from].push_back(edge(to,cost));
104             G2[to].push_back(edge(from,cost));
105         }
106         dijkstra_g1(x);
107 
108         dijkstra_g2(x);
109         int maxn=ans[0];
110         for(int i=0;i<maxv;i++)
111             if(ans[i]>maxn)
112                 maxn=ans[i];
113         printf("%d\n",maxn);
114 
115     }
116     return 0;
117 }

 

poj 1258

kurskal模板题

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int maxv=100+5;
 5 int pa[maxv];
 6 struct edge
 7 {
 8     int x,y,cost;
 9 };
10 void init_union(int V)
11 {
12     for(int i=1;i<=V;i++)
13     {
14         pa[i]=i;
15     }
16 }
17 
18 int Find(int x)
19 {
20     if(pa[x]==x)
21         return pa[x];
22     else return pa[x]=Find(pa[x]);
23 }
24 
25 bool same(int x,int y)
26 {
27     return (Find(x)==Find(y))?true:false;
28 
29 }
30 
31 void join(int x,int y)
32 {
33     int fx=Find(x);
34     int fy=Find(y);
35     if(fx!=fy)
36     {
37         pa[fx]=fy;
38     }
39 }
40 
41 bool cmp(const edge& e1,const edge& e2)
42 {
43     return e1.cost<e2.cost;
44 }
45 edge es[maxv];
46 int V,E;
47 
48 int kruskal()
49 {
50     sort(es,es+E,cmp);
51     init_union(V);
52     int res=0;
53     for(int i=0;i<E;i++)
54     {
55         edge e=es[i];
56         if(!same(e.x,e.y))
57         {
58             join(e.x,e.y);
59             res+=e.cost;
60         }
61     }
62     return res;
63 }
64 
65 int main()
66 {
67     while(~scanf("%d",&V))
68     {
69         E=0;
70         for(int i=1;i<=V;i++)
71         {
72             for(int j=1;j<=V;j++)
73             {
74                 es[E].x=i;
75                 es[E].y=j;
76                 scanf("%d",&es[E].cost);
77                 E++;
78             }
79         }
80         printf("%d\n",kruskal());
81     }
82 
83     return 0;
84 }

 

poj 2377

最大权生成树,kruskal改动一下cmp函数就行了。

 

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int maxv=1000+5;
 5 const int maxe=20000+50;
 6 int V,E;
 7 int pa[maxv];
 8 struct edge
 9 {
10     int x,y,cost;
11 }es[maxe];
12 void init(int n)
13 {
14     for(int i=1;i<=n;i++)
15     {
16         pa[i]=i;
17     }
18 }
19 int Find(int x)
20 {
21     if(x==pa[x])
22         return x;
23     else
24         return pa[x]=Find(pa[x]);
25 }
26 bool same(int x,int y)
27 {
28     return (Find(x)==Find(y))?true:false;
29 }
30 void join(int x,int y)
31 {
32     int fx=Find(x);
33     int fy=Find(y);
34     if(fx!=fy)
35         pa[fx]=fy;
36 }
37 bool cmp(const edge& a,const edge& b)
38 {
39     return a.cost>b.cost;
40 }
41 int kruskal()
42 {
43     int ans=0;
44     int cnt=0;
45     sort(es,es+E,cmp);
46     for(int i=0;i<E;i++)
47     {
48         edge e=es[i];
49         if(!same(e.x,e.y))
50         {
51             join(e.x,e.y);
52             ans+=e.cost;
53             cnt++;
54         }
55     }
56     if(cnt!=V-1)
57         return -1;
58     else return ans;
59 }
60 int main()
61 {
62     while(~scanf("%d%d",&V,&E))
63     {
64         init(V);
65         for(int i=0;i<E;i++)
66         {
67             scanf("%d%d%d",&es[i].x,&es[i].y,&es[i].cost);
68         }
69         printf("%d\n",kruskal());
70     }
71     return 0;
72 }

 

 

 

poj 2395

 

 

 

附上几个模板

spfa判断负环模板

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
int n,m,w;
const int maxv=500+5;
const int INF=0x3f3f3f3f;
int vis[maxv],cnt[maxv],dis[maxv];

struct Node
{
    int to,weight;
    Node(int too,int wei):to(too),weight(wei){}
};
vector<Node>G[maxv];
void ma_init()
{
    for(int i=1;i<=n;i++)//vector要记得重置
        G[i].clear();
     ................
}

bool spfa(int s)
{
    memset(vis,0,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++)//初始化distant数组
        dis[i]=INF;
    //进队之前的初始化
    queue<int>que;
    dis[s]=0;
    que.push(s);
    vis[s]=cnt[s]=1;

    while(!que.empty())
    {
        //取出队列中队首的顶点的编号fv
        int fv=que.front();

        for(int i=0;i<G[fv].size();i++)//对顶点fv,的所有相连的边进行一次遍历。
        {
            //G[fv][[i]这条边的from为顶点fv,它的to和weight分别用fto和fwei取出来
            int fto=G[fv][i].to;
            int fwei=G[fv][i].weight;
            //进行更新
            if(dis[fto] > dis[fv]+fwei)
            {
                dis[fto]=dis[fv]+fwei;
                //若顶点fto此时不在队列中
                if(vis[fto] == 0)
                {//则压进栈中,并更新一系列数据
                    que.push(fto);
                    vis[fto]=1;
                    cnt[fto]++;
                    if(cnt[fto]>n-1) //如果有一个顶点进队了n次,则存在负环
                        return true;
                }
            }
        }
        que.pop();
        vis[fv]=0;//弹出之后消除标记
    }
    return false;
}

dijkstra模板

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int maxv=1000+5;
const int INF=0x3f3f3f3f;
typedef pair<int,int>P;
int d[maxv],ans[maxv];
int n,m,x;
struct edge
{
    int to,cost;
    edge(int t,int c):to(t),cost(c){}
    bool operator <(const edge& a)const
    {
        if(cost!=a.cost) return cost > a.cost;
        else return to < a.to;
    }
};

vector<edge>G1[maxv];
vector<edge>G2[maxv];
void ma_init()
{
    for(int i=0;i<maxv;i++)
    {
        G[i].clear();
    }
}

void dijkstra_g1(int s)
{
    for(int i=0;i<maxv;i++)
        d[i]=INF;

    priority_queue<P>que;
    d[s]=0;
    que.push(P(d[s],s));
    while(!que.empty())
    {
        P p = que.top();que.pop();
        int v=p.second;
        if(d[v] < p.first) continue;
        for(int i=0;i<G[v].size();i++)
        {
            edge e = G[v][i];
            if(d[e.to] > d[v] + e.cost )
            {
                d[e.to] = d[v] + e.cost;
                que.push(P(d[e.to],e.to));
            }
        }
    }
}

最小生成树 kruskal模板

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxv=100+5;
int V,E;
int pa[maxv];
struct edge
{
    int x,y,cost;
};
void init_union(int V)
{
    for(int i=1;i<=V;i++)
    {
        pa[i]=i;
    }
}

int Find(int x)
{
    if(pa[x]==x)
        return pa[x];
    else return pa[x]=Find(pa[x]);
}

bool same(int x,int y)
{
    return (Find(x)==Find(y))?true:false;

}

void join(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy)
    {
        pa[fx]=fy;
    }
}

bool cmp(const edge& e1,const edge& e2)
{
    return e1.cost<e2.cost;
}
edge es[maxv];

int kruskal()
{
    sort(es,es+E,cmp);
    init_union(V);
    int res=0;
    for(int i=0;i<E;i++)
    {
        edge e=es[i];
        if(!same(e.x,e.y))
        {
            join(e.x,e.y);
            res+=e.cost;
        }
    }
    return res;
}

 

《挑战程序设计竞赛》2.5 它们其实都是图

标签:

原文地址:http://www.cnblogs.com/luosuo10/p/5666358.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!