标签:
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; }
标签:
原文地址:http://www.cnblogs.com/luosuo10/p/5666358.html