图论相关

Posted yijiull

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论相关相关的知识,希望对你有一定的参考价值。

 

最小生成树:

 

畅通工程

HDU - 1232
 
只要互相间接通过道路可达即可,说明只要最后是一棵树就可以. 树的边数为顶点数减1.
用并查集求出当前已有的边数, 再用 n-1减去就是还需要再建的路.
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<string>
 6 using namespace std;
 7 const int maxn=1010;
 8 int f[maxn];
 9 int n,m;
10 void init()
11 {
12     for(int i=0;i<=n;i++)
13         f[i]=i;
14 }
15 int  gf(int x)
16 {
17     return x==f[x]?x:f[x]=gf(f[x]);
18 }
19 void unit(int x,int y)
20 {
21     int px=gf(x);
22     int py=gf(y);
23     f[px]=py;
24 }
25 
26 int main()
27 {
28     while(cin>>n&&n)
29     {
30         cin>>m;
31         int cnt=0;
32         init();
33         int x,y;
34         for(int i=0;i<m;i++){
35             cin>>x>>y;
36                 if(gf(x)!=gf(y)) {unit(x,y);cnt++;}
37         }
38         cout<<n-1-cnt<<endl;
39     }
40 }
View Code

 


还是畅通工程

HDU - 1233
和ppt上讲的一样,就是最小生成树的模板题, 先对边进行排序, 然后用并查集维护一下,就可以了.
 
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 int f[105];
 6    int n;
 7 struct Edge
 8 {
 9     int x,y,w;
10     bool operator <(const Edge &a)const
11     {
12         return w<a.w;
13     }
14 }e[10010];
15 void init()
16 {
17     for(int i=0;i<=n;i++)
18         f[i]=i;
19 }
20 int  gf(int x)
21 {
22     return x==f[x]?x:f[x]=gf(f[x]);
23 }
24 void unit(int x,int y)
25 {
26     int px=gf(x);
27     int py=gf(y);
28     f[px]=py;
29 }
30 
31 int main()
32 {
33 
34     while(cin>>n&&n)
35     {
36         init();
37         int cnt=0;
38         int ans=0;
39         int m=n*(n-1)/2;
40         for(int i=0;i<m;i++)
41             cin>>e[i].x>>e[i].y>>e[i].w;
42         sort(e,e+m);
43         for(int i=0;i<m;i++)
44         {
45             if(gf(e[i].x)!=gf(e[i].y)) {
46                     ans+=e[i].w;
47                     unit(e[i].x,e[i].y);
48                     cnt++;
49             }
50             if(cnt==n-1) break;    //已经是树, 跳出循环
51         }
52         cout<<ans<<endl;
53 
54     }
55 }
View Code

 

 

 

Building a Space Station

POJ - 2031
 

求出任意两点之间的距离减去两个点的半径。

然后求最小生成树.

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=110;
 7 int n;
 8 int f[maxn];
 9 struct node
10 {
11     double x,y,z;
12     double r;
13 }p[maxn];
14 
15 struct edge
16 {
17     int u,v;
18     double w;
19     bool operator < (const edge &a)
20     {
21         return w<a.w;
22     }
23 }e[100010];
24 
25 double getdis(int  i,int j)
26 {
27     double dx=p[i].x-p[j].x;
28     double dy=p[i].y-p[j].y;
29     double dz=p[i].z-p[j].z;
30     return sqrt(dx*dx+dy*dy+dz*dz)-p[i].r-p[j].r;
31 }
32 
33 void init()
34 {
35     for(int i=0;i<n;i++)
36         f[i]=i;
37 }
38 
39 int gf(int a)
40 {
41     return a==f[a]?a:f[a]=gf(f[a]);
42 }
43 
44 void uni(int a,int b)
45 {
46     int pa=gf(a);
47     int pb=gf(b);
48     f[pb]=pa;
49 }
50 
51 int main()
52 {
53     while(scanf("%d",&n)&&n)
54     {
55         init();
56         for(int i=0;i<n;i++)
57         {
58             scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z,&p[i].r);
59         }
60         int cnt=0;
61         for(int i=0;i<n;i++)
62             for(int j=i+1;j<n;j++)
63         {
64             e[cnt].u=i;
65             e[cnt].v=j;
66             e[cnt].w=getdis(i,j);
67             cnt++;
68         }
69         double ans=0;
70         sort(e,e+cnt);
71         for(int i=0;i<cnt;i++)
72         {
73             if(e[i].w<=0) uni(e[i].u,e[i].v);
74           else   if(gf(e[i].u)!=gf(e[i].v))  {ans+=e[i].w; uni(e[i].u,e[i].v);}
75         }
76         printf("%.3f\\n",ans);
77     }
78 }
View Code

 

最短路:

有选择的看一下这篇博客:  链接

链式钱向星 链接

 

Heavy Transportation

POJ - 1797
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1010;
 7 int pic[maxn][maxn];
 8 int vis[maxn];
 9 int dc[maxn];
10 int t,n,m;
11 void dijkstra()
12 {
13 
14 
15     for(int j=0;j<n;j++)
16     {
17      int m=-1,x;
18      for(int i=1;i<=n;i++)
19         if(!vis[i]&&dc[i]>m) m=dc[x=i];
20         vis[x]=1;
21      for(int i=1;i<=n;i++)
22          if(!vis[i]&&dc[i]<min(dc[x],pic[x][i]))
23          {
24              dc[i]=min(dc[x],pic[x][i]);
25          }
26 
27     }
28 
29 
30 }
31 
32 int main()
33 {
34     scanf("%d",&t);
35     int u,v,w;
36     for(int i=1;i<=t;i++)
37     {
38         scanf("%d%d",&n,&m);
39         memset(pic,0,sizeof(pic));
40         while(m--)
41         {
42             scanf("%d%d%d",&u,&v,&w);
43             pic[u][v]=pic[v][u]=w;
44         }
45         for(int i=1;i<=n;i++)
46         {
47             vis[i]=0;
48             dc[i]=pic[1][i];
49         }
50         dijkstra();
51         printf("Scenario #%d:\\n%d\\n\\n",i,dc[n]);
52     }
53     return 0;
54 
55 }
View Code

 

MPI Maelstrom

POJ - 1502
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<string>
 4 #include<iostream>
 5 using namespace std;
 6 const int inf=0x3f3f3f3f;
 7 int pic[110][110];
 8 int vis[110];
 9 int dis[110];
10 
11 int n;
12 
13 void dijkstra()
14 {
15     for(int i=1;i<=n;i++){
16             dis[i]=inf;
17             vis[i]=0;
18     }
19     dis[1]=0;
20     for(int i=0;i<n;i++)
21     {
22         int x,m=inf;
23         for(int y=1;y<=n;y++) if(!vis[y]&&m>dis[y]) m=dis[x=y];
24         vis[x]=1;
25         for(int y=1;y<=n;y++) if(!vis[y]&&dis[y]>dis[x]+pic[x][y]) dis[y]=dis[x]+pic[x][y];
26     }
27 }
28 
29 int tran(string s)
30 {
31     int len=s.length();
32     int d=0;
33     for(int i=0;i<len;i++)
34         d=d*10+(s[i]-\'0\');
35 return d;
36 }
37 int main()
38 {
39 
40 int d;
41     string s;
42     while(scanf("%d",&n)!=EOF)
43     {
44 
45         for(int i=1;i<=n;i++)
46             for(int j=1;j<=n;j++)
47             pic[i][j]=(i==j?0:inf);
48         for(int i=2;i<=n;i++)
49             for(int j=1;j<i;j++)
50         {
51                 cin>>s;
52                 if(s=="x") continue;
53                 else {
54 
55                 d=tran(s);
56                  pic[i][j]=pic[j][i]=d;
57                 }
58 
59 
60         }
61          dijkstra();
62         int ans=-1;
63 
64         for(int i=2;i<=n;i++)
65             ans=max(ans,dis[i]);
66         printf("%d\\n",ans);
67     }
68 }
View Code

 

Til the Cows Come Home

POJ - 2387

优化过的dijkstra

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<queue>
 4 using namespace std;
 5 const int maxn=1050;
 6 const int maxe=5100;
 7 int t,n;
 8 int head[maxn];
 9 int dis[maxn];
10 typedef pair<int,int> P;
11 struct node
12 {
13     int v,w,nex;
14 }edge[maxe];
15 
16 int cnt;
17 
18 void add(int u,int v,int w)
19 {
20     edge[cnt].v=v;
21     edge[cnt].w=w;
22     edge[cnt].nex=head[u];
23     head[u]=cnt++;
24 }
25 int dijkstra()
26 {
27     priority_queue<P,vector<P>,greater<P> > pq;
28     P p;
29     node e;
30     int v;
31     for(int i=0;i<=n;i++)
32         dis[i]=999999;
33     dis[n]=0;
34     pq.push(P(0,n));
35        while(!pq.empty())
36         {
37             p=pq.top();
38             pq.pop();
39             v=p.second;
40             if(dis[v]<p.first) continue;
41             for(int i=head[v];i!=-1;i=edge[i].nex)
42             {
43                 e=edge[i];
44                 if(dis[e.v]>e.w+dis[v])
45                 {
46                     dis[e.v]=e.w+dis[v];
47                     pq.push(P(dis[e.v],e.v));
48                 }
49             }
50         }
51         printf("%d\\n",dis[1]);
52 }
53 int main()
54 {
55     while(scanf("%d%d",&t,&n)!=EOF)
56     {
57         cnt=0;
58         int u,v,w;
59         memset(head,-1,sizeof(head));
60         while(t--)
61         {
62             scanf("%d%d%d",&u,&v,&w);
63             add(u,v,w);
64             add(v,u,w);
65         }
66         dijkstra();
67 
68     }
69 }
View Code

 

 

以上是关于图论相关的主要内容,如果未能解决你的问题,请参考以下文章

MT90图论基础知识及相关例题

结论图论相关结论

图论相关

图论-相关概念

N囚徒挑战——一个图论相关的概率问题

图论之二分图-HihoCoder1121