最短路拓展

 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=1e6+10;
 8 const int inf=1e9;
 9 struct node{
10     int v;
11     int c;
12     node(int _v=0,int _c=0):v(_v),c(_c) {}
13     bool operator < (const node &r)const{
14     return c>r.c;
15     }
16 };
17 struct Edge{
18     int v,cost;
19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
20 };
21 vector<Edge>E[maxn];
22 bool vis[maxn];
23 int dist[maxn];
24 int n,s;
25 
26 void addedge(int u,int v,int w)
27 {
28     E[u].push_back(Edge(v,w));
29 }
30 
31 void dij()
32 {
33     memset(vis,false,sizeof(vis));
34     for ( int i=1;i<=n;i++ ) dist[i]=inf;
35     priority_queue<node>que;
36     while ( !que.empty() ) que.pop();
37     dist[s]=0;
38     que.push(node(s,0));
39     node tmp;
40     while ( !que.empty() )
41     {
42         tmp=que.top();
43         que.pop();
44         int u=tmp.v;
45         if ( vis[u] ) continue;
46         vis[u]=true;
47         for ( int i=0;i<E[u].size();i++ )
48         {
49             int v=E[u][i].v;
50             int cost=E[u][i].cost;
51             if ( !vis[v] && dist[v]>dist[u]+cost )
52             {
53                 dist[v]=dist[u]+cost;
54                 que.push(node(v,dist[v]));
55             }
56         }
57     }
58 }
Dijkstra算法模板
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=1010;
 8 const int inf=1e9;
 9 struct Edge{
10     int v;
11     int cost;
12     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
13 }; 
14 vector<Edge>E[maxn];
15 bool vis[maxn];
16 int cnt[maxn];
17 int dist[maxn];
18 int s,n;
19 
20 void addedge(int u,int v,int w)
21 {
22     E[u].push_back(Edge(v,w));
23 }
24 
25 bool spfa()
26 {
27     memset(vis,false,sizeof(vis));
28     for ( int i=1;i<=n;i++ ) dist[i]=inf;
29     vis[s]=true;
30     dist[s]=0;
31     queue<int>que;
32     while ( !que.empty() ) que.pop();
33     que.push(s);
34     memset(cnt,0,sizeof(cnt));
35     cnt[s]=1;
36     while ( !que.empty() )
37     {
38         int u=que.front();
39         que.pop();
40         vis[u]=false;
41         for ( int i=0;i<E[u].size();i++ )
42         {
43             int v=E[u][i].v;
44             int cost=E[u][i].cost;
45             if ( dist[v]>dist[u]+cost )
46             {
47                 dist[v]=dist[u]+cost;
48                 if ( !vis[v] )
49                 {
50                     vis[v]=true;
51                     que.push(v);
52                     if ( ++cnt[v]>n ) return false;    
53                 }    
54             }
55         }
56     }
57     return true;
58 }
Spfa模板

 

1.(UVA247)https://vjudge.net/problem/UVA-247

题意:给定n个人和m组关系(x,y表示x打电话给y,单向),找出所有的环,分别输出每个环内的元素

分析:当vis[x][y]=vis[y][x]=true表示这两个点处于一个环内,利用floyd传递闭包,最后注意输出格式

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<map>
 5 #include<string>
 6 #include<iostream>
 7 #include<vector>
 8 using namespace std;
 9 const int maxn=30;
10 map<string,int>mp;
11 map<int,string>mp_;
12 bool vis[maxn][maxn];
13 int belong[maxn];
14 vector<int>G[maxn];
15 
16 int main()
17 {
18     int n,m,cnt,num,id1,id2,h=0;
19     string s1,s2;
20     while ( scanf("%d%d",&n,&m)!=EOF && (n+m) )
21     {
22         mp.clear();
23         mp_.clear();
24         memset(vis,false,sizeof(vis));
25         memset(belong,0,sizeof(belong));
26         for ( int i=1;i<=n;i++ ) 
27         {
28             vis[i][i]=true;
29             G[i].clear();
30         }
31         cnt=0;
32         for ( int i=1;i<=m;i++ )
33         {
34             cin>>s1>>s2;
35             if ( mp.find(s1)==mp.end() ) mp[s1]=++cnt,mp_[cnt]=s1;
36             id1=mp[s1];
37             if ( mp.find(s2)==mp.end() ) mp[s2]=++cnt,mp_[cnt]=s2;
38             id2=mp[s2];
39             vis[id1][id2]=true;
40         }
41         for ( int k=1;k<=n;k++ )
42         {
43             for ( int i=1;i<=n;i++ )
44             {
45                 for ( int j=1;j<=n;j++ )
46                 {
47                     if ( vis[i][k] && vis[k][j] ) vis[i][j]=true;    
48                 }    
49             } 
50         }
51         num=0;
52         for ( int i=1;i<=n;i++ )
53         {
54             if ( belong[i] ) continue;
55             belong[i]=++num;
56             G[num].push_back(i);
57             for ( int j=i+1;j<=n;j++ )
58             {
59                 if ( belong[j] ) continue;
60                 if ( vis[i][j] && vis[j][i] ) 
61                 {
62                     belong[j]=belong[i];
63                     G[num].push_back(j);
64                 }
65             }
66         }
67         if ( h ) printf("\n");
68         printf("Calling circles for data set %d:\n",++h);
69         for ( int i=1;i<=num;i++ )
70         {
71             for ( int j=0;j<G[i].size();j++ )
72             {
73                 cout<<mp_[G[i][j]];
74                 if ( j<G[i].size()-1 ) printf(", ");
75                 else printf("\n");
76             }
77         }
78     }
79     return 0;
80 }
UVA247

 

2.(UVA10048)https://vjudge.net/problem/UVA-10048

题意:给定c个点和s条边的有向图,边权代表该路径上的噪音值。每次询问输入两个点,求这两个点间最大噪音值最小的值

 分析:Dijkstra算法中每次松弛将本来的dist[v]=dist[u]+cost变成dist[v]=max(dist[u],cost) (在满足条件的前提下)

floyd算法松弛过程同Dijkastra

 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=110;
 8 const int inf=1e9;
 9 struct node{
10     int v;
11     int c;
12     node(int _v=0,int _c=0):v(_v),c(_c) {}
13     bool operator < (const node &r)const{
14     return c>r.c;
15     }
16 };
17 struct Edge{
18     int v,cost;
19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
20 };
21 vector<Edge>E[maxn];
22 bool vis[maxn];
23 int dist[maxn][maxn];
24 int n;
25 
26 void addedge(int u,int v,int w)
27 {
28     E[u].push_back(Edge(v,w));
29 }
30 
31 void dij(int s)
32 {
33     memset(vis,false,sizeof(vis));
34     for ( int i=1;i<=n;i++ ) dist[s][i]=inf;
35     priority_queue<node>que;
36     while ( !que.empty() ) que.pop();
37     dist[s][s]=0;
38     que.push(node(s,0));
39     node tmp;
40     while ( !que.empty() )
41     {
42         tmp=que.top();
43         que.pop();
44         int u=tmp.v;
45         if ( vis[u] ) continue;
46         vis[u]=true;
47         for ( int i=0;i<E[u].size();i++ )
48         {
49             int v=E[u][i].v;
50             int cost=E[u][i].cost;
51             int x=max(cost,dist[s][u]);
52             if ( !vis[v] && dist[s][v]>x )
53             {
54                 dist[s][v]=x;
55                 que.push(node(v,dist[s][v]));
56             }
57         }
58     }
59 }
60 
61 int main()
62 {
63     int m,q,h=0;
64     while ( scanf("%d%d%d",&n,&m,&q)!=EOF && (n+m+q) )
65     {
66         for ( int i=1;i<=n;i++ )
67         {
68             for ( int j=1;j<=n;j++ ) dist[i][j]=inf;
69             dist[i][i]=0;
70             E[i].clear();
71         }
72         for ( int i=1;i<=m;i++ )
73         {
74             int u,v,w;
75             scanf("%d%d%d",&u,&v,&w);
76             addedge(u,v,w);
77             addedge(v,u,w);
78         }
79         for ( int i=1;i<=n;i++ )
80         {
81             dij(i);
82         }
83         if ( h ) printf("\n");
84         printf("Case #%d\n",++h);
85         while ( q-- )
86         {
87             int u,v;
88             scanf("%d%d",&u,&v);
89             if ( dist[u][v]==inf ) printf("no path\n");
90             else printf("%d\n",dist[u][v]);
91         }
92     }
93     return 0;
94 }
UVA10048(Dijkstra)
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=110;
 6 const int inf=1e9;
 7 int dist[maxn][maxn];
 8 
 9 void floyd(int n)
10 {
11     for ( int k=1;k<=n;k++ )
12     {
13         for ( int i=1;i<=n;i++ )
14         {
15             for ( int j=1;j<=n;j++ )
16             {
17                 if ( dist[i][k]==inf || dist[k][j]==inf ) continue;
18                 if ( dist[i][j]==inf ) dist[i][j]=max(dist[i][k],dist[k][j]);
19                 else dist[i][j]=min(dist[i][j],max(dist[i][k],dist[k][j]));
20             }
21         }
22     }
23 }
24 
25 int main()
26 {
27     int n,m,q,h=0;
28     while ( scanf("%d%d%d",&n,&m,&q)!=EOF && (n+m+q) )
29     {
30         for ( int i=1;i<=n;i++ )
31         {
32             for ( int j=1;j<=n;j++ ) dist[i][j]=inf;
33             dist[i][i]=0;
34         }
35         for ( int i=1;i<=m;i++ )
36         {
37             int u,v,w;
38             scanf("%d%d%d",&u,&v,&w);
39             dist[u][v]=min(dist[u][v],w);
40             dist[v][u]=min(dist[v][u],w);
41         }
42         floyd(n);
43         if ( h ) printf("\n");
44         printf("Case #%d\n",++h);
45         while ( q-- )
46         {
47             int u,v;
48             scanf("%d%d",&u,&v);
49             if ( dist[u][v]==inf ) printf("no path\n");
50             else printf("%d\n",dist[u][v]);
51         }
52     }
53     return 0;
54 }
UVA10048(floyd)

 

3.(UVA658)https://vjudge.net/problem/UVA-658

题意:有一个长度为n的bug,有m个补丁,每个补丁有3个值,分别代表花费的时间,bug在补丁前的状态(“0”代表无所谓,“-”代表bug不存在,“+”代表bug存在),bug在补丁后的状态(“0”代表不变,“+”代表该位置出现bug,“-”代表该位置没有bug),一个补丁可以打多次,求最小的花费时间

分析:将bug转化为二进制形式,0表示该位置有bug,1表示该位置没有bug。所以总共有(1<<n)-1种状态。每次更新时访问所有的补丁(可以等效成“边”) ,若满足条件则转移状态,最后判断(1<<n)-1这个状态

  1 #include<cstdio> 
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn=2e6+10;
  8 const int N=22;
  9 const int maxm=110;
 10 const int inf=1e9;
 11 struct node{
 12     int v;
 13     int c;
 14     node(int _v=0,int _c=0):v(_v),c(_c) {}
 15     bool operator < (const node &r)const{
 16     return c>r.c;
 17     }
 18 };
 19 bool vis[maxn];
 20 int dist[maxn];
 21 int s;
 22 char s1[maxm][N],s2[maxm][N];
 23 int w[maxm],m;
 24 
 25 void dij(int n)
 26 {
 27     memset(vis,false,sizeof(vis));
 28     for ( int i=0;i<=n;i++ ) dist[i]=inf;
 29     priority_queue<node>que;
 30     while ( !que.empty() ) que.pop();
 31     dist[s]=0;
 32     que.push(node(s,0));
 33     node tmp;
 34     while ( !que.empty() )
 35     {
 36         tmp=que.top();
 37         que.pop();
 38         int u=tmp.v;
 39         if ( vis[u] ) continue;
 40         vis[u]=true;
 41         for ( int i=1;i<=m;i++ )
 42         {
 43             bool flag=true;
 44             int len=strlen(s1[i]);
 45             for ( int j=0;j<len;j++ )
 46             {
 47                 if ( s1[i][j]=='0' ) continue;
 48                 else if ( s1[i][j]=='+' )
 49                 {
 50                     if ( ((1<<j)&u) )
 51                     {
 52                         flag=false;
 53                         break;
 54                     }
 55                 }
 56                 else if ( s1[i][j]=='-' ) 
 57                 {
 58                     if ( !((1<<j)&u) )
 59                     {
 60                         flag=false;
 61                         break;
 62                     }    
 63                 } 
 64             }
 65             if ( !flag ) continue;
 66             int v=u;
 67             for ( int j=0;j<len;j++ )
 68             {
 69                 if ( s2[i][j]=='0' ) continue;
 70                 else if ( s2[i][j]=='+' )
 71                 {
 72                     if ( ((1<<j)&v) ) v^=(1<<j);
 73                 }
 74                 else if ( s2[i][j]=='-' ) 
 75                 {
 76                     if ( !((1<<j)&v) ) v|=(1<<j);
 77                 } 
 78             }
 79             int cost=w[i];
 80             if ( !vis[v] && dist[v]>dist[u]+cost )
 81             {
 82                 dist[v]=dist[u]+cost;
 83                 que.push(node(v,dist[v]));
 84             }
 85         }
 86     }
 87 }
 88 
 89 int main()
 90 {
 91     int n,h=0,p;
 92     while ( scanf("%d%d",&n,&m)!=EOF && (n+m) ) 
 93     {
 94         p=(1<<n)-1;
 95         for ( int i=1;i<=m;i++ )
 96         {
 97             scanf("%d%s%s",&w[i],s1[i],s2[i]);
 98         }
 99         s=0;
100         dij(p);
101         printf("Product %d\n",++h);
102         if ( dist[p]!=inf ) printf("Fastest sequence takes %d seconds.\n\n",dist[p]);
103         else printf("Bugs cannot be fixed.\n\n");
104     }
105     return 0;
106 }
UVA658

 

4.(UVA11374)https://vjudge.net/problem/UVA-11374

题意:机场快线分为经济线和商业线,你有一张商业线的车票,可以坐一站商业线,其他时候都只能做经济线,不考虑换乘时间,求一条最快去机场的线路。输入第一行为n,s,e,分别表示点数,起点和终点。下一行一个m表示经济线的线路数,接下来m行有x,y,z表示x-y(双向)花费z分钟。接下来一行一个k表示商业线的线路数,接下来k行x,y,z表示x-y(双向)花费z。输出三行,第一行表示线路,第二行表示换乘商业线的编号,第三行表示时间

分析:首先需要分别以s和e为起点进行两次最短路算法。剩下的只要枚举坐的是哪趟商业线即可,对于任意一条含商业线的路线所花费的时间为d(s,x)+z+d(y,e)与d(s,e)进行比较即可。注意如何打印路径。

  1 #include<cstdio> 
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn=5010;
  8 const int maxm=5010;
  9 const int inf=1e9;
 10 struct node{
 11     int v;
 12     int c;
 13     node(int _v=0,int _c=0):v(_v),c(_c) {}
 14     bool operator < (const node &r)const{
 15     return c>r.c;
 16     }
 17 };
 18 struct Edge{
 19     int v,cost;
 20     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
 21 };
 22 vector<Edge>E[maxn];
 23 bool vis[maxn];
 24 int dist[2][maxn];
 25 int pre[2][maxn];
 26 int n;
 27 int a[maxm],b[maxm],c[maxm];
 28 
 29 void addedge(int u,int v,int w)
 30 {
 31     E[u].push_back(Edge(v,w));
 32 }
 33 
 34 void dij(int s)
 35 {
 36     memset(vis,false,sizeof(vis));
 37     for ( int i=1;i<=n;i++ ) dist[0][i]=inf;
 38     memset(pre[0],-1,sizeof(pre[0]));
 39     priority_queue<node>que;
 40     while ( !que.empty() ) que.pop();
 41     dist[0][s]=0;
 42     que.push(node(s,0));
 43     node tmp;
 44     while ( !que.empty() )
 45     {
 46         tmp=que.top();
 47         que.pop();
 48         int u=tmp.v;
 49         if ( vis[u] ) continue;
 50         vis[u]=true;
 51         for ( int i=0;i<E[u].size();i++ )
 52         {
 53             int v=E[u][i].v;
 54             int cost=E[u][i].cost;
 55             if ( !vis[v] && dist[0][v]>dist[0][u]+cost )
 56             {
 57                 dist[0][v]=dist[0][u]+cost;
 58                 pre[0][v]=u;
 59                 que.push(node(v,dist[0][v]));
 60             }
 61         }
 62     }
 63 }
 64 
 65 void display(int u)
 66 {
 67     if ( pre[0][u]==-1 )
 68     {
 69         printf("%d",u);
 70         return;
 71     }
 72     display(pre[0][u]);
 73     printf(" %d",u);
 74 }
 75 
 76 int main()
 77 {
 78     int s,e,k,ans,cnt,m,h=0;
 79     while ( scanf("%d%d%d",&n,&s,&e)!=EOF )
 80     {
 81         for ( int i=1;i<=n;i++ ) E[i].clear();
 82         scanf("%d",&m);
 83         for ( int i=1;i<=m;i++ )
 84         {
 85             int u,v,w;
 86             scanf("%d%d%d",&u,&v,&w);
 87             addedge(u,v,w);
 88             addedge(v,u,w);
 89         }
 90         dij(e);
 91         for ( int i=1;i<=n;i++ )
 92         {
 93             dist[1][i]=dist[0][i];
 94             pre[1][i]=pre[0][i];
 95         }
 96         dij(s);
 97         scanf("%d",&k);
 98         for ( int i=1;i<=k*2;i+=2 )
 99         {
100             scanf("%d%d%d",&a[i],&b[i],&c[i]);
101             b[i+1]=a[i];
102             a[i+1]=b[i];
103             c[i+1]=c[i];
104         }
105         ans=dist[0][e];
106         cnt=-1;
107         for ( int i=1;i<=2*k;i++ )
108         {
109             int num=dist[0][a[i]]+c[i]+dist[1][b[i]];
110             if ( num<ans )
111             {
112                 ans=num;
113                 cnt=i;
114             }
115         }
116         if ( h++>0 ) printf("\n");
117         if ( cnt==-1 ) 
118         {
119             display(e);
120             printf("\n");
121             printf("Ticket Not Used\n");
122         }
123         else 
124         {
125             display(a[cnt]);
126             for ( int i=b[cnt];i!=e;i=pre[1][i] ) printf(" %d",i);
127             printf(" %d\n",e);
128             printf("%d\n",a[cnt]);
129         }
130         printf("%d\n",ans);
131     }
132     return 0;
133 }
UVA11374

 

5.(UVA10917)https://vjudge.net/problem/UVA-10917

题意:有n个点和m条双向边,从起点1出发,去往终点2.每次只沿着满足如下条件道路的(A,B)走,存在一条从B出发的路,比所有从A出发回家的路都短。计算一共有多少条路

 分析:最短路+dfs,首先用最短路求出所有点到终点2的距离(用来判断某条边是否可走),设dp[i]为从i出发有多少条路可以到达终点,初始化dp[1]=1,其余均为0.然后通过dfs,从1出发。对于点u来说,当边(u,v)满足条件,则dp[u]+=dp[v]

 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=1e3+10;
 8 const int inf=1e9;
 9 struct node{
10     int v;
11     int c;
12     node(int _v=0,int _c=0):v(_v),c(_c) {}
13     bool operator < (const node &r)const{
14     return c>r.c;
15     }
16 };
17 struct Edge{
18     int v,cost;
19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
20 };
21 vector<Edge>E[maxn];
22 bool vis[maxn];
23 int dist[maxn],dp[maxn];
24 int n,s,e;
25 
26 void addedge(int u,int v,int w)
27 {
28     E[u].push_back(Edge(v,w));
29 }
30 
31 void dij()
32 {
33     memset(vis,false,sizeof(vis));
34     for ( int i=1;i<=n;i++ ) dist[i]=inf;
35     priority_queue<node>que;
36     while ( !que.empty() ) que.pop();
37     dist[s]=0;
38     que.push(node(s,0));
39     node tmp;
40     while ( !que.empty() )
41     {
42         tmp=que.top();
43         que.pop();
44         int u=tmp.v;
45         if ( vis[u] ) continue;
46         vis[u]=true;
47         for ( int i=0;i<E[u].size();i++ )
48         {
49             int v=E[u][i].v;
50             int cost=E[u][i].cost;
51             if ( !vis[v] && dist[v]>dist[u]+cost )
52             {
53                 dist[v]=dist[u]+cost;
54                 que.push(node(v,dist[v]));
55             }
56         }
57     }
58 }
59 
60 int dfs(int u)
61 {
62     vis[u]=true;
63     for ( int i=0;i<E[u].size();i++ )
64     {
65         int v=E[u][i].v;
66         if ( dist[v]>=dist[u] ) continue;
67         if ( vis[v] ) dp[u]+=dp[v];
68         else dp[u]+=dfs(v);
69     }
70     return dp[u];
71 }
72 
73 int main()
74 {
75     int m;
76     while ( scanf("%d",&n)!=EOF && n )
77     {
78         scanf("%d",&m);
79         for ( int i=1;i<=n;i++ ) E[i].clear();
80         s=2;
81         e=1;
82         for ( int i=1;i<=m;i++ )
83         {
84             int u,v,w;
85             scanf("%d%d%d",&u,&v,&w);
86             addedge(u,v,w);
87             addedge(v,u,w);
88         }
89         dij();
90         memset(dp,0,sizeof(dp));
91         memset(vis,false,sizeof(vis));    
92         dp[s]=1;
93         //vis[e]=true;
94         dfs(e);
95         printf("%d\n",dp[1]);
96     }
97     return 0;
98 }
UVA10917

 

6.(UVA10537)https://vjudge.net/problem/UVA-10537

题意:运送货物需要缴纳路费,路过一个村庄需要缴纳一个单位的货物,路过城镇每20个货物需要缴纳1个单位的货物(70个需要缴纳4个)。输入时给定一个n表示道路的条数,接下来n行,每行两个字母(大写为城镇,小写为村庄),道路均为双向路。接下来一行包括一个p和两个字母,表示运送的货物数量、起点和终点。输出包括运送货物的最小值和对应线路(若有多条线路,输出字典序最小的)

分析:用最短算法的逆推,设dist[i] 表示进入节点后至少有dist[i]单位的货物才能使达到目的地的货物数量足够,每次选择一个dist[i]最小的未标号结点,更新它所有的前驱,算出所有的dist。假设经过某个城镇后的数量为x,若x%19==0,则y=x/19。若x%19!=0,则y=x/19+1。则y为在该城镇所缴纳的货物

注意:dist数组开longlong,图为无向图,可以直接用字符的阿斯克码当作结点的编号,注意打印路径的写法

 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 typedef long long ll; 
 8 const int maxn=155;
 9 const int n=150;
10 const ll inf=1e18;
11 struct node{
12     int v;
13     ll c;
14     node(int _v=0,ll _c=0):v(_v),c(_c) {}
15     bool operator < (const node &r)const{
16         return c>r.c;
17     }
18 };
19 vector<int>E[maxn];
20 bool vis[maxn];
21 ll dist[maxn],num;
22 int s,e,pre[maxn];
23 
24 void addedge(int u,int v)
25 {
26     E[u].push_back(v);
27 }
28 
29 void dij()
30 {
31     memset(vis,false,sizeof(vis));
32     memset(pre,-1,sizeof(pre));
33     for ( int i=0;i<=n;i++ ) dist[i]=inf;
34     priority_queue<node>que;
35     while ( !que.empty() ) que.pop();
36     dist[s]=num;
37     que.push(node(s,dist[s]));
38     node tmp;
39     while ( !que.empty() )
40     {
41         tmp=que.top();
42         que.pop();
43         int u=tmp.v;
44         if ( vis[u] ) continue;
45         vis[u]=true;
46         for ( int i=0;i<E[u].size();i++ )
47         {
48             int v=E[u][i];
49             if ( vis[v] ) continue;
50             ll cost;
51             if ( u>='a' ) cost=1;
52             else 
53             {
54                 if ( tmp.c%19==0 ) cost=tmp.c/19;
55                 else cost=tmp.c/19+1;    
56             }
57             if (dist[v]>dist[u]+cost || (dist[v]==dist[u]+cost&&pre[v]>u) )
58             {
59                 pre[v]=u;
60                 dist[v]=dist[u]+cost;
61                 que.push(node(v,dist[v]));
62             }
63         }
64     }
65 }
66 
67 int main()
68 {
69     int m,h=0;
70     char s1[10],s2[10];
71     while ( scanf("%d",&m)!=EOF && m!=-1 )
72     {
73         for ( int i=0;i<=n;i++ ) E[i].clear();
74         for ( int i=1;i<=m;i++ )
75         {
76             int u,v;
77             scanf("%s%s",s1,s2);
78             u=s1[0];
79             v=s2[0];
80             addedge(v,u);
81             addedge(u,v);
82         }
83         scanf("%lld%s%s",&num,s1,s2);
84         e=s1[0];
85         s=s2[0];
86         dij();
87         printf("Case %d:\n%lld\n",++h,dist[e]);
88         while ( e!=s )
89         {
90             printf("%c-",e);
91             e=pre[e];
92         }
93         printf("%c\n",s);
94     }
95     return 0;
96 }
UVA10537

 

7.(UVA11090)https://vjudge.net/problem/UVA-11090

题意:给定一个n个点和m条边的加权有向图,求平均权值最小的回路。

分析:二分+SPFA判负环,首先二分平均值,在进行一次SPFA判断有无负环的存在。在SPFA过程中,因为起初没有起点,所有需要将所有点都存入队列中

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 #include<cmath>
 7 using namespace std;
 8 const double eps=1e-6;
 9 const int maxn=60;
10 const int inf=1e9;
11 struct Edge{
12     int v;
13     double cost;
14     Edge(int _v=0,double _cost=0):v(_v),cost(_cost) {}
15 }; 
16 vector<Edge>E[maxn];
17 bool vis[maxn];
18 int cnt[maxn];
19 double dist[maxn];
20 int n;
21 
22 void addedge(int u,int v,double w)
23 {
24     E[u].push_back(Edge(v,w));
25 }
26 
27 bool spfa(double m)
28 {
29     queue<int>que;
30     while ( !que.empty() ) que.pop();
31     for ( int i=1;i<=n;i++ )
32     {
33         dist[i]=0;
34         que.push(i);
35         vis[i]=true;
36         cnt[i]=1;
37     }
38     while ( !que.empty() )
39     {
40         int u=que.front();
41         que.pop();
42         vis[u]=false;
43         for ( int i=0;i<E[u].size();i++ )
44         {
45             int v=E[u][i].v;
46             double cost=E[u][i].cost-m;
47             if ( dist[v]>dist[u]+cost )
48             {
49                 dist[v]=dist[u]+cost;
50                 if ( !vis[v] )
51                 {
52                     vis[v]=true;
53                     que.push(v);
54                     if ( ++cnt[v]>n ) return false;    
55                 }    
56             }
57         }
58     }
59     return true;
60 }
61 
62 int main()
63 {
64     int T,m;
65     double l,r,mid;
66     scanf("%d",&T);
67     for ( int h=1;h<=T;h++ )
68     {
69         scanf("%d%d",&n,&m);
70         for ( int i=1;i<=n;i++ ) E[i].clear();
71         for ( int i=1;i<=m;i++ )
72         {
73             int u,v;
74             double w;
75             scanf("%d%d%lf",&u,&v,&w);
76             addedge(u,v,w);
77         }
78         printf("Case #%d: ",h);
79         l=0,r=10000000;
80         while ( r-l>eps )
81         {
82             mid=(l+r)/2;
83             if ( spfa(mid) ) l=mid;
84             else r=mid;
85         }
86         if ( abs(l-1e7)<eps ) printf("No cycle found.\n");
87         else printf("%.2lf\n",l);
88     }
89     return 0;
90 }
UVA11090

 

8.(UVA11478)https://vjudge.net/problem/UVA-11478

题意:给定一个有向图,每条边有一个权值。每次可以选择一个节点u和一个整数d,把所有以u为终点的边的权值减小d,把所有以u为起点的边的权值增加d,最后要让所有边权中的最小值非负且尽量大

分析:注意不同的操作之间互不影响,因此可以按任意顺序实施这些操作。另外对于同一个点的多次操作也可以合并。因此可以设置sum(u)表示所有在结点u上进行的操作。二分答案x,对于边(a,b)来说可以得到sum(b)-sum(a)<=w(a,b) -x,这样就转化为差分约束系统了。当出现负环时表示不存在该答案。判断二分的左右区间,若右边界的答案存在则值无限,若左边界的答案不存在则值不存在

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=510;
 8 const int inf=1e4;
 9 struct edge{
10     int v,cost;
11     edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
12 };
13 vector<edge>E[maxn];
14 bool vis[maxn];
15 int cnt[maxn],dist[maxn],s,n;
16 bool flag;
17 
18 void addedge(int u,int v,int w)
19 {
20     E[u].push_back(edge(v,w));
21 }
22 
23 bool SPFA(int mid)
24 {
25     memset(vis,false,sizeof(vis));
26     memset(cnt,0,sizeof(cnt));
27     for ( int i=0;i<=n;i++ ) dist[i]=inf;
28     vis[s]=true;
29     dist[s]=0;
30     queue<int>que;
31     que.push(s);
32     cnt[s]=1;
33     while ( !que.empty() ) {
34         int u=que.front();
35         que.pop();
36         vis[u]=false;
37         for ( int i=0;i<E[u].size();i++ ) {
38             int v=E[u][i].v;
39             int cost;
40             cost=E[u][i].cost-mid;
41             if ( dist[v]>dist[u]+cost ) {
42                 dist[v]=dist[u]+cost;
43                 if ( !vis[v] ) {
44                     vis[v]=true;
45                     que.push(v);
46                     if ( ++cnt[v]>(n+1) ) return false;
47                 }
48             }
49         }
50     }
51     return true;
52 }
53 
54 bool judge(int mid)
55 {
56     bool ok=SPFA(mid);
57     if ( ok ) return flag=true;
58     return false;
59 }
60 
61 int main()
62 {
63     int m,l,r,mid;
64     while ( scanf("%d%d",&n,&m)!=EOF )
65     {
66         flag=false;
67         for ( int i=0;i<=n;i++ ) E[i].clear();
68         s=0;
69         for ( int i=1;i<=n;i++ ) addedge(s,i,0);
70         for ( int i=1;i<=m;i++ )
71         {
72             int u,v,w;
73             scanf("%d%d%d",&u,&v,&w);
74             addedge(u,v,w);
75         }
76         l=1;
77         r=inf;
78         if ( judge(r) ) printf("Infinite\n");
79         else if ( !judge(l) ) printf("No Solution\n");
80         else
81         {
82             while ( r-l>1 )
83             {
84                 mid=(l+r)/2;
85                 if ( judge(mid) ) l=mid;
86                 else r=mid;
87             }
88             printf("%d\n",l);    
89         }
90     }
91     return 0;
92 }
UVA11478

 

9.(POJ3255)http://poj.org/problem?id=3255

题意:求次短路

分析:次短路模板题

 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=1e4+10;
 8 const int inf=1e9;
 9 struct node{
10     int v;
11     int c;
12     node(int _v=0,int _c=0):v(_v),c(_c) {}
13     bool operator < (const node &r)const{
14     return c>r.c;
15     }
16 };
17 struct Edge{
18     int v,cost;
19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
20 };
21 vector<Edge>E[maxn];
22 bool vis[maxn];
23 int dist[2][maxn];
24 int n,s;
25 
26 void addedge(int u,int v,int w)
27 {
28     E[u].push_back(Edge(v,w));
29 }
30 
31 void dij()
32 {
33     for ( int i=1;i<=n;i++ ) 
34     {
35         dist[0][i]=inf;
36         dist[1][i]=inf;
37     }
38     priority_queue<node>que;
39     while ( !que.empty() ) que.pop();
40     dist[0][s]=0;
41     que.push(node(s,0));
42     node tmp;
43     while ( !que.empty() )
44     {
45         tmp=que.top();
46         que.pop();
47         int u=tmp.v;
48         if ( dist[1][u]<tmp.c ) continue;
49         for ( int i=0;i<E[u].size();i++ )
50         {
51             int v=E[u][i].v;
52             int cost=E[u][i].cost;
53             int d2=tmp.c+cost;
54             if ( dist[0][v]>d2 )
55             {
56                 swap(dist[0][v],d2);
57                 que.push(node(v,dist[0][v]));
58             }
59             if ( dist[1][v]>d2 && dist[0][v]<d2 )
60             {
61                 dist[1][v]=d2;
62                 que.push(node(v,dist[1][v]));
63             }
64         }
65     }
66 }
67 
68 int main()
69 {
70     int m;
71     while ( scanf("%d%d",&n,&m)!=EOF )
72     {
73         for ( int i=1;i<=n;i++ ) E[i].clear();
74         for ( int i=1;i<=m;i++ )
75         {
76             int u,v,w;
77             scanf("%d%d%d",&u,&v,&w);
78             addedge(u,v,w);
79             addedge(v,u,w);
80         }
81         s=1;
82         dij();
83         printf("%d\n",dist[1][n]);
84     }
85     return 0;
86 }
POJ3255(次短路模板题)

 

10.(luoguP2371)https://www.luogu.org/problemnew/show/P2371

分析:同余最短路。(给定一些数去求一个更大的数是否可能由这些数组成)

首先求出n=min{ai},若x能被凑出,则x+mn也能被凑出。

建n个点(0到n-1),dis[i]分别表示模mn意义下余i的能凑出的数最小为多少。

对于每一个ai,从x向(x+ai)%mn连一条边权为ai的边。

求最短路,则最后求得dis[i],计算一下就可以了。

 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 typedef long long ll;
 8 const int maxN=15;
 9 const int maxn=5e5+10;
10 const ll inf=1e18;
11 struct node{
12     int v;
13     ll c;
14     node(int _v=0,ll _c=0):v(_v),c(_c) {}
15     bool operator < (const node &r)const{
16     return c>r.c;
17     }
18 };
19 struct Edge{
20     int v;
21     ll cost;
22     Edge(int _v=0,ll _cost=0):v(_v),cost(_cost) {}
23 };
24 vector<Edge>E[maxn];
25 bool vis[maxn];
26 ll dist[maxn];
27 int n,s;
28 int a[maxN];
29 
30 void addedge(int u,int v,ll w)
31 {
32     E[u].push_back(Edge(v,w));
33 }
34 
35 void dij()
36 {
37     for ( int i=0;i<n;i++ ) dist[i]=inf,vis[i]=false;
38     priority_queue<node>que;
39     while ( !que.empty() ) que.pop();
40     dist[s]=0;
41     que.push(node(s,0));
42     node tmp;
43     while ( !que.empty() )
44     {
45         tmp=que.top();
46         que.pop();
47         int u=tmp.v;
48         if ( vis[u] ) continue;
49         vis[u]=true;
50         for ( int i=0;i<E[u].size();i++ )
51         {
52             int v=E[u][i].v;
53             if ( vis[v] ) continue;
54             ll cost=E[u][i].cost;
55             if ( dist[v]>dist[u]+cost )
56             {
57                 dist[v]=dist[u]+cost;
58                 que.push(node(v,dist[v]));
59             }
60         }
61     }
62 }
63 
64 int main()
65 {
66     int N;
67     ll L,R,ans;
68     while ( scanf("%d%lld%lld",&N,&L,&R)!=EOF )
69     {
70         for ( int i=1;i<=N;i++ ) scanf("%d",&a[i]);
71         sort(a+1,a+1+N);
72         n=a[1];
73         for ( int i=0;i<n;i++ ) E[i].clear();
74         s=0;
75         for ( int i=0;i<n;i++ )
76         {
77             for ( int j=2;j<=N;j++ ) 
78             {
79                 if ( (a[j]+i)%n!=0 ) addedge(i,(a[j]+i)%n,1ll*a[j]);
80             }
81         }
82         ans=0;
83         dij();
84         L--;
85         for ( int i=0;i<n;i++ )
86         {
87             if ( dist[i]<=L ) ans-=(L-dist[i])/n+1;
88             if ( dist[i]<=R ) ans+=(R-dist[i])/n+1;
89         }
90         printf("%lld\n",ans);
91     }
92     return 0;
93 }
P2371

 

11.(luoguP2662)https://www.luogu.org/problemnew/show/P2662

分析:同余最短路,将所有可能出现的长度加入c[]数组,取出最小的作为n,剩余的按照上一题的方式建边。最后的答案应该为ans=max(dist[i]-n),即某一同余类中最大的不能组成数的大小。若ans为初始值0,则不存在最大值,输出-1

注意:最后的答案计算的方式

 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=3e3+10;
 8 const int inf=1e9;
 9 struct node{
10     int v;
11     int c;
12     node(int _v=0,int _c=0):v(_v),c(_c) {}
13     bool operator < (const node &r)const{
14     return c>r.c;
15     }
16 };
17 struct Edge{
18     int v,cost;
19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
20 };
21 vector<Edge>E[maxn];
22 bool vis[maxn],b[maxn];
23 int dist[maxn];
24 int n,s;
25 int a[maxn],c[maxn];
26 
27 void addedge(int u,int v,int w)
28 {
29     E[u].push_back(Edge(v,w));
30 }
31 
32 void dij()
33 {
34     memset(vis,false,sizeof(vis));
35     for ( int i=0;i<n;i++ ) dist[i]=inf;
36     priority_queue<node>que;
37     while ( !que.empty() ) que.pop();
38     dist[s]=0;
39     que.push(node(s,0));
40     node tmp;
41     while ( !que.empty() )
42     {
43         tmp=que.top();
44         que.pop();
45         int u=tmp.v;
46         if ( vis[u] ) continue;
47         vis[u]=true;
48         for ( int i=0;i<E[u].size();i++ )
49         {
50             int v=E[u][i].v;
51             int cost=E[u][i].cost;
52             if ( !vis[v] && dist[v]>dist[u]+cost )
53             {
54                 dist[v]=dist[u]+cost;
55                 que.push(node(v,dist[v]));
56             }
57         }
58     }
59 }
60 
61 int main()
62 {
63     int N,M,m,ans;
64     while ( scanf("%d%d",&N,&M)!=EOF )
65     {
66         memset(b,false,sizeof(b));
67         for ( int i=1;i<=N;i++ ) 
68         {
69             scanf("%d",&a[i]);
70             b[a[i]]=true;
71             for ( int j=a[i]-1;j>=a[i]-M&&j>0;j-- ) b[j]=true;
72         }
73         m=0;
74         for ( int i=1;i<=3000;i++ )
75         {
76             if ( b[i] ) c[++m]=i;
77         }
78         n=c[1];
79         for ( int i=0;i<n;i++ ) E[i].clear();
80         for ( int i=0;i<n;i++ )
81         {
82             for ( int j=2;j<=m;j++ )
83             {
84                 if ( (i+c[j])%n!=0 ) addedge(i,(i+c[j])%n,c[j]);
85             }
86         }
87         s=0;
88         dij();
89         ans=0;
90         for ( int i=0;i<n;i++ ) 
91         {
92             if ( dist[i]!=inf ) ans=max(ans,dist[i]-n);
93         }
94         if ( ans!=0 ) printf("%d\n",ans);
95         else printf("-1\n");
96     }
97     return 0;
98 }
P2662

 

12.(HDOJ3873)http://acm.hdu.edu.cn/showproblem.php?pid=3873

 题意:有一个n个点和m条边的有向图,起点为1,终点为n,对于第i个点来说会被in[i]个点所保护,只有先到那些保护它的点后才能到该点(可以同时有多支队伍)。求到达终点的最短时间

分析:dij的变形,设置in[i]为保护i的点还有in[i]个,val[i]为到达所有保护点i的点需要的最少的时间.每次访问点u时将它保护的点v进行更新数组in[v]和val[v],当in[v]==0&&dist[v]!=inf时,点v可以入队

  1 #include<cstdio> 
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn=1e6+10;
  8 const int inf=1e9;
  9 struct node{
 10     int v;
 11     int c;
 12     node(int _v=0,int _c=0):v(_v),c(_c) {}
 13     bool operator < (const node &r)const{
 14     return c>r.c;
 15     }
 16 };
 17 struct Edge{
 18     int v,cost;
 19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
 20 };
 21 vector<Edge>E[maxn];
 22 vector<int>G[maxn];
 23 bool vis[maxn];
 24 int dist[maxn],in[maxn],val[maxn];
 25 int n,s;
 26 
 27 void addedge(int u,int v,int w)
 28 {
 29     E[u].push_back(Edge(v,w));
 30 }
 31 
 32 void dij()
 33 {
 34     memset(vis,false,sizeof(vis));
 35     for ( int i=1;i<=n;i++ ) dist[i]=inf;
 36     priority_queue<node>que;
 37     while ( !que.empty() ) que.pop();
 38     dist[s]=0;
 39     que.push(node(s,0));
 40     node tmp;
 41     while ( !que.empty() )
 42     {
 43         tmp=que.top();
 44         que.pop();
 45         int u=tmp.v;
 46         if ( vis[u] ) continue;
 47         vis[u]=true;
 48         for ( int i=0;i<G[u].size();i++ )
 49         {
 50             int v=G[u][i];
 51             in[v]--;
 52             val[v]=max(val[v],dist[u]);
 53             if ( dist[v]!=inf && !in[v] )
 54             {
 55                 dist[v]=max(dist[v],val[v]);
 56                 que.push(node(v,dist[v]));
 57             }
 58         }
 59         for ( int i=0;i<E[u].size();i++ )
 60         {
 61             int v=E[u][i].v;
 62             if ( vis[v] ) continue;
 63             int cost=E[u][i].cost;
 64             if ( dist[v]>cost+dist[u] )
 65             {
 66                 dist[v]=cost+dist[u];
 67                 if ( !in[v] ) que.push(node(v,dist[v]));
 68             }
 69         }
 70     }
 71 }
 72 
 73 int main()
 74 {
 75     int T,m;
 76     scanf("%d",&T);
 77     while ( T-- )
 78     {
 79         scanf("%d%d",&n,&m);
 80         s=1;
 81         for ( int i=1;i<=n;i++ ) 
 82         {
 83             E[i].clear();
 84             G[i].clear();
 85             val[i]=0;
 86         }
 87         for ( int i=1;i<=m;i++ )
 88         {
 89             int u,v,w;
 90             scanf("%d%d%d",&u,&v,&w);
 91             addedge(u,v,w);
 92         }
 93         for ( int i=1;i<=n;i++ )
 94         {
 95             scanf("%d",&in[i]);
 96             for ( int j=1;j<=in[i];j++ )
 97             {
 98                 int x;
 99                 scanf("%d",&x);
100                 G[x].push_back(i);
101             }
102         }
103         dij();
104         printf("%d\n",dist[n]);
105     }
106     return 0;
107 }
HDOJ3873

 

13.(HDOJ4845)http://acm.hdu.edu.cn/showproblem.php?pid=4845

分析:状态压缩+DFS,利用分层思想建立模型,用二进制代表所拿到的钥匙(状态),不同的状态对应不同的图。

设置数组dp[i][j][k]表示从(1,1,0)到(i,j,k)(横坐标为x,纵坐标为y,状态为k)需要的步数,vis[i][j][k]代表有无访问过。key[i][j]代表坐标(i,j)所包含的钥匙状态,从(1,1,0)开始跑BFS即可

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 const int maxn=18;
 7 const int maxm=12;
 8 const int inf=1e9;
 9 struct node{
10     int x,y,sta;
11     node(int _x=0,int _y=0,int _sta=0):x(_x),y(_y),sta(_sta) {}
12 };
13 int door[maxn][maxn][maxn][maxn];
14 int key[maxn][maxn],dp[maxn][maxn][1<<maxm];
15 bool vis[maxn][maxn][1<<maxm];
16 int n,m,p,s;
17 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
18 
19 void BFS()
20 {
21     memset(vis,false,sizeof(vis));
22     for ( int i=1;i<=n;i++ )
23     {
24         for ( int j=1;j<=m;j++ )
25         {
26             for ( int k=0;k<1<<(s+1);k++ ) dp[i][j][k]=inf;
27         }
28     }
29     dp[1][1][0]=0;
30     vis[1][1][0]=0;
31     queue<node>que;
32     que.push(node(1,1,0));
33     while ( !que.empty() )
34     {
35         node tmp=que.front();
36         que.pop();
37         int x=tmp.x,y=tmp.y,sta=tmp.sta;
38         if ( x==n && y==m ) return;
39         for ( int i=0;i<4;i++ )
40         {
41             int fx=x+dir[i][0];
42             int fy=y+dir[i][1];
43             int h=door[x][y][fx][fy];
44             int sta_=sta|key[fx][fy];
45             int t;
46             if ( h!=-1 ) t=sta&(1<<h);
47             if ( h==0 || (h!=-1 && t==0) ) continue;
48             if ( fx<=0 || fx>n || fy<=0 || fy>m || vis[fx][fy][sta_] ) continue;
49             vis[fx][fy][sta_]=true;
50             que.push(node(fx,fy,sta_));
51             dp[fx][fy][sta_]=dp[x][y][sta]+1;
52         }
53     }
54     return;
55 }
56 
57 int main()
58 {
59     int k,ans;
60     while ( scanf("%d%d%d",&n,&m,&p)!=EOF )
61     {
62         memset(door,-1,sizeof(door));
63         memset(key,0,sizeof(key));
64         scanf("%d",&k);
65         for ( int i=1;i<=k;i++ )
66         {
67             int x1,x2,y1,y2,g;
68             scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
69             door[x1][y1][x2][y2]=door[x2][y2][x1][y1]=g;
70         }
71         scanf("%d",&s);
72         for ( int i=1;i<=s;i++ )
73         {
74             int x,y,g;
75             scanf("%d%d%d",&x,&y,&g);
76             key[x][y]|=(1<<g);
77         }
78         BFS();
79         ans=-1;
80         for ( int i=0;i<1<<(s+1);i++ )
81         {
82             if ( dp[n][m][i]!=inf ) ans=dp[n][m][i];
83         }
84         if ( ans==inf ) printf("-1\n");
85         else printf("%d\n",ans);
86     }
87     return 0;
88 }
HDOJ4845

 

posted @ 2018-08-02 09:29  HDU_jackyan  阅读(321)  评论(0编辑  收藏  举报