标签:
A. POJ 2387 Til the Cows Come Home
模板题.
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; const int INF =1000000000; int mincost[1010]; int cost[1010][1010]; bool used[1010]; int main() { int T,N; while(cin>>T>>N) { int from,to,w; memset(cost,0x3f,sizeof(cost)); for(int i=0;i<T;i++) { cin>>from>>to>>w; cost[from][to]=cost[to][from]=min(cost[from][to],w); } memset(mincost,0x3f,sizeof(mincost)); memset(used,0,sizeof(used)); mincost[1]=0; while(1) { int v=-1; for(int u=1;u<=N;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=true; for(int u=1;u<=N;u++) mincost[u]=min(mincost[u],mincost[v]+cost[u][v]); } printf("%d\n",mincost[N]); } return 0; }
B. POJ 2253 Frogger
模板题.把任意两块石头之间的距离算出来作为最短路.然后套模板.
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; struct Point{ int x,y; }point[250]; double dist[250][250]; double lowedge[250]; bool used[250]; double fun(int i,int j) { return sqrt((double)(point[i].x-point[j].x)*(point[i].x-point[j].x)+(point[i].y-point[j].y)*(point[i].y-point[j].y)); } int n; int main() { int icase=0; while(cin>>n&&n) { memset(dist,0,sizeof(dist)); for(int i=0;i<n;i++) { cin>>point[i].x>>point[i].y; for(int j=0;j<i;j++) dist[i][j]=dist[j][i]=fun(i,j); } for(int i=0;i<n;i++) lowedge[i]=dist[0][i]; memset(used,0,sizeof(used)); lowedge[0]=0; while(1) { int v=-1; for(int u=0;u<n;u++) if(!used[u]&&(v==-1||lowedge[u]<lowedge[v])) v=u; if(v==-1) break; used[v]=true; for(int u=0;u<n;u++) if(!used[u]&&max(lowedge[v],dist[v][u])<lowedge[u]) lowedge[u]=max(lowedge[v],dist[u][v]); } printf("Scenario #%d\n",++icase); printf("Frog Distance = %.3f\n\n",lowedge[1]); } return 0; }
C. POJ 1797 Heavy Transportation
题意:求出起点到终点的每条路径的最小权值中最大的那个权值。
思路:选择dist[u]和cost[u][v]中较小的那个来收缩dist[v].
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int dist[1100][1100]; int mincost[1100]; bool used[1100]; int n,m; int main() { int T,icase=0; cin>>T; while(T--) { cin>>n>>m; int x,y,w; memset(dist,0,sizeof(dist)); for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&w); dist[x][y]=dist[y][x]=w; } memset(used,0,sizeof(used)); for(int i=1;i<=n;i++) mincost[i]=dist[1][i]; while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[u]&&(v==-1||mincost[u]>mincost[v])) v=u; if(v==-1) break; used[v]=true; for(int u=1;u<=n;u++) if(!used[u]&&min(mincost[v],dist[v][u])>mincost[u]) mincost[u]=min(mincost[v],dist[v][u]); } printf("Scenario #%d:\n",++icase); printf("%d\n\n",mincost[n]); } return 0; }
D. POJ 3286 Silver Cow Party
题意:有N个农场,每个农场有一头牛。农场X举行party,其他农场的牛前去参加,然后在回家。求所有牛来回距离之和的
最小值。
思路:先用dijkstra求目标点到个点的最短路。然后再建立一个反图,即将每一条反向。再求一次 目标点到每个点的最短路,
两个最短路的各点距离之和即为所求。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int dist[1100][1100]; int mincost[2][1100]; bool used[2][1100]; int n,m,t; int main() { while(cin>>n>>m>>t) { int x,y,w; memset(dist,0x3f,sizeof(dist)); for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&w); dist[x][y]=w; } memset(used,0,sizeof(used)); memset(mincost,0x3f,sizeof(mincost)); mincost[0][t]=mincost[1][t]=0; while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[0][u]&&(v==-1||mincost[0][u]<mincost[0][v])) v=u; if(v==-1) break; used[0][v]=true; for(int u=1;u<=n;u++) if(!used[0][u]&&mincost[0][u]>mincost[0][v]+dist[v][u]) mincost[0][u]=mincost[0][v]+dist[v][u]; } while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[1][u]&&(v==-1||mincost[1][u]<mincost[1][v])) v=u; if(v==-1) break; used[1][v]=true; for(int u=1;u<=n;u++) if(!used[1][u]&&mincost[1][u]>mincost[1][v]+dist[u][v]) mincost[1][u]=mincost[1][v]+dist[u][v]; } int ans=0; for(int i=1;i<=n;i++) ans=max(ans,mincost[0][i]+mincost[1][i]); printf("%d\n",ans); } return 0; }
E. POJ 1860 Currency Exchange
题意:存在N种货币,M种交换规则。每个交换规则在两种货币之间交换,交换有手续费和汇率。
交换所得=(交换金额-手续费)*汇率。问你是否存在一种交换使得你的金钱变多。
思路:通过bell_man算法 循环n-1次。然后再枚举每一条边,看还能否松弛,如果可以就说明存
在这样的交换。否则不存在。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; struct edge{ int from,to; double r,c; }ed[220]; int dist[1100][1100]; double mincost[110]; bool used[110]; int n,m,s; double v; int main() { int from,to; double r1,c1,r2,c2; while(cin>>n>>m>>s>>v) { int flag=0; memset(ed,0,sizeof(ed)); memset(mincost,0,sizeof(mincost)); for(int i=0;i<m;i++) { cin>>from>>to>>r1>>c1>>r2>>c2; ed[2*i].from=from; ed[2*i].to=to; ed[2*i].r=r1; ed[2*i].c=c1; ed[2*i+1].from=to; ed[2*i+1].to=from; ed[2*i+1].r=r2; ed[2*i+1].c=c2; } mincost[s]=v; for(int i=1;i<n;i++) { int update=0; for(int j=0;j<2*m;j++) if(mincost[ed[j].to]<(mincost[ed[j].from]-ed[j].c)*ed[j].r) update=1,mincost[ed[j].to]=(mincost[ed[j].from]-ed[j].c)*ed[j].r; if(!update) break; } for(int j=0;j<2*m;j++) if(mincost[ed[j].to]<(mincost[ed[j].from]-ed[j].c)*ed[j].r) { flag=1; break; } printf("%s\n",flag?"YES":"NO"); } return 0; }
F. POJ 3259 Wormholes
题意:有N个农场,M条边,W个虫洞。虫洞相当于一条权值为负的边。问你是否存在一条路径使得你回到出发时间之前。
思路:同上题基本一样。只是松弛的方式不同。这道题同样是通过bell_man算法 循环n-1次。然后再枚举每一条边,看是否还能松弛,如果可以,就存在这样的路径,否则不存在。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; struct edge{ int from,to,w; }ed[5500]; double mincost[550]; int n,m,w,t; int main() { cin>>t; while(t--) { memset(ed,0,sizeof(ed)); memset(ed,0x3f,sizeof(mincost)); int from,to,cost,flag=0; cin>>n>>m>>w; for(int i=0;i<m;i++) { cin>>from>>to>>cost; ed[2*i].from=ed[2*i+1].to=from; ed[2*i].to=ed[2*i+1].from=to; ed[2*i].w=ed[2*i+1].w=cost; } for(int i=0;i<w;i++) { cin>>from>>to>>cost; ed[i+2*m].from=from; ed[i+2*m].to=to; ed[i+2*m].w=cost*(-1); } for(int i=1;i<n;i++) { int update=0; for(int j=0;j<2*m+w;j++) if(mincost[ed[j].to]>mincost[ed[j].from]+ed[j].w) update=1,mincost[ed[j].to]=mincost[ed[j].from]+ed[j].w; if(!update) break; } for(int j=0;j<2*m+w;j++) if(mincost[ed[j].to]>mincost[ed[j].from]+ed[j].w) { flag=1; break; } printf("%s\n",flag?"YES":"NO"); } return 0; }
G POJ 1502 MPI Maelstrom
题意:给你n个节点,给你一个下三角矩阵,描述两点之间传送消息的cost,‘X’表示这两点之间不能直接发送消息。询问第一个节点到其他所有节点发送消息的花费的最小值。
思路:直接dijkstra就好,难点在于输入矩阵的处理。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int n; int dist[110][110]; int mincost[110]; bool used[110]; int strtoint(char* str) { if (str[0] == ‘x‘) return -1; int ret = 0; while (*str) { ret = ret * 10 + *str++ - ‘0‘; } return ret; } int main() { char str[35]; int dis; scanf("%d",&n); for (int i = 0; i < n; ++i) { for (int j = 0; j < i; ++j) { scanf("%s", str); dis = strtoint(str); dist[i][j] = dist[j][i] = dis; } } memset(mincost,0x3f,sizeof(mincost)); mincost[0]=0; while(1) { int v=-1; for(int u=0;u<n;u++) if(!used[u]&&(v==-1||mincost[v]>mincost[u])) v=u; if(v==-1) break; used[v]=true; for(int u=0;u<n;u++) if(dist[u][v]>=0) mincost[u]=min(mincost[u],mincost[v]+dist[u][v]); } int ans=0; for(int i=0;i<n;i++) ans=max(ans,mincost[i]); printf("%d\n",ans); return 0; }
H POJ 3660 Cow Contest
题意:有n头牛,每一头牛都有一定的编程能力值。需要将这些牛根据他们的编程能力值排序。已知任意两头牛之间可以比赛,编程能力值高的获胜。现在告诉你m个胜负关系。
询问能确定位置的牛有多少头。
思路:这个题挺有意思。先通过floyd算法得到任意两头牛之间的rank高低。然后根据传递闭包,求出每一头牛的度数(出度+入度),然后判断,如果一个点的度数等于n-1,
则这个点的位置就是确定的。最后统计,输出答案。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int ma[110][110]; int de[110]; int main() { int n,m,from,to,ans=0; cin>>n>>m; memset(de,0,sizeof(de)); memset(ma,0,sizeof(ma)); for(int i=0;i<m;i++) { cin>>from>>to; ma[from][to]=1; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) if(ma[j][i]&&ma[i][k]) ma[j][k]=1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(ma[i][j]) { de[i]++; de[j]++; } for(int i=1;i<=n;i++) if(de[i]==n-1) ans++; printf("%d\n",ans); return 0; }
I POJ 2240 Arbitrage
题意:告诉你n种货比两两之间的汇率,询问是否可能通过交换使钱变多。
思路:floyd算法,然后看是否存在dist[i][i]>1,即通过交换使得钱变多。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; map<string,int> m; double dist[50][50]; int main() { int n,d,icase=0; string str1,str2; double w; while(cin>>n&&n) { int flag=0; memset(dist,0,sizeof(dist)); for(int i=0;i<n;i++) { cin>>str1; m[str1]=i; dist[i][i]=1; } cin>>d; for(int i=0;i<d;i++) { cin>>str1>>w>>str2; dist[m[str1]][m[str2]]=w; } for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) dist[j][k]=max(dist[j][k],dist[j][i]*dist[i][k]); for(int i=0;i<n;i++) if(dist[i][i]>1) { flag=1; break; } printf("Case %d: %s\n",++icase,flag?"Yes":"No"); } return 0; }
J POJ 1511 Invitation Cards
题意:早上从某一点出发去所有其他点发传单,然后晚上在回来。求总的最小花费。
思路:思路跟D题几乎一样,但是数据很大,需要用SPFA来做。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<set> #include<map> #include<string> #include<math.h> #include<cctype> #define ll long long #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t)) #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--) #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t)) #define PII pair<int,int> #define fst first #define snd second #define MP make_pair #define PB push_back #define RI(x) scanf("%d",&(x)) #define RII(x,y) scanf("%d%d",&(x),&(y)) #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z)) #define DRI(x) int (x);scanf("%d",&(x)) #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y)) #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z)) #define RS(x) scanf("%s",x) #define RSS(x,y) scanf("%s%s",x,y) #define DRS(x) char x[maxn];scanf("%s",x) #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y) #define MS0(a) memset((a),0,sizeof((a))) #define MS1(a) memset((a),-1,sizeof((a))) #define MS(a,b) memset((a),(b),sizeof((a))) #define ALL(v) v.begin(),v.end() #define SZ(v) (int)(v).size() #define maxn 1000100 #define INF (1LL<<60) using namespace std; int C,M,S,T,P,Q; bool vis[maxn]; ll dist[maxn]; int c[maxn]; struct Edge { int v; ll w; Edge *next; };Edge e1[maxn],e2[maxn]; bool relax(int u,int v,ll w) { if(dist[u]+w<dist[v]){ dist[v]=dist[u]+w; return true; } return false; } void add_edge(int u,int v,ll w,Edge *e) { Edge *pre=&e[u]; Edge *p=(Edge*)malloc(sizeof(Edge)); p->v=v;p->w=w; p->next=pre->next; pre->next=p; } bool spfa(Edge *e) { for(int i=1;i<=P;i++) dist[i]=(i==S)?0:INF; memset(vis,0,sizeof(vis)); memset(c,0,sizeof(c)); queue<int> q; q.push(S); vis[S]=1;c[S]++; while(!q.empty()){ int u=q.front();q.pop();vis[u]=0; for(Edge *p=e[u].next;p!=NULL;p=p->next){ int v=p->v; ll w=p->w; if(relax(u,v,w)){ if(!vis[v]){ q.push(v); vis[v]=1; c[v]++; if(c[v]>P) return false; } } } } return true; } int main() { // freopen("in.txt","r",stdin); scanf("%d",&C); while(C--) { int u,v; ll w,ans=0; S=1; MS0(e1); MS0(e2); scanf("%d%d",&P,&Q); for(int i=0;i<Q;i++) { scanf("%d%d%lld",&u,&v,&w); add_edge(u,v,w,e1); add_edge(v,u,w,e2); } spfa(e1); for(int i=2;i<=P;i++) ans+=dist[i]; spfa(e2); for(int i=2;i<=P;i++) ans+=dist[i]; printf("%lld\n",ans); } return 0; }
K POJ 3159 Candies
题意:题目告诉你n个人,有m个关系 b的糖果不能比a的糖果多c个,问最后一个人最多拥有多少个糖果。
思路:SPFA最短路,松弛条件换成dist[v]=min(dist[v],dist[u]+w);
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<set> #include<map> #include<string> #include<math.h> #include<cctype> #define ll long long #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t)) #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--) #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t)) #define PII pair<int,int> #define fst first #define snd second #define MP make_pair #define PB push_back #define RI(x) scanf("%d",&(x)) #define RII(x,y) scanf("%d%d",&(x),&(y)) #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z)) #define DRI(x) int (x);scanf("%d",&(x)) #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y)) #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z)) #define RS(x) scanf("%s",x) #define RSS(x,y) scanf("%s%s",x,y) #define DRS(x) char x[maxn];scanf("%s",x) #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y) #define MS0(a) memset((a),0,sizeof((a))) #define MS1(a) memset((a),-1,sizeof((a))) #define MS(a,b) memset((a),(b),sizeof((a))) #define ALL(v) v.begin(),v.end() #define SZ(v) (int)(v).size() #define maxn 1000100 #define INF (1LL<<60) using namespace std; struct Edge { int v; ll w; Edge *next; }e[35000]; bool vis[35000]; ll dist[35000]; bool relax(int u,int v,ll w) { if(dist[u]+w<dist[v]) { dist[v]=dist[u]+w; return true; } return false; } void add_edge(int u,int v,ll w) { Edge *pre=&e[u]; Edge *p=(Edge *)malloc(sizeof(Edge)); p->v=v;p->w=w; p->next=pre->next; pre->next=p; } void spfa() { for(int i=0;i<35000;i++) dist[i]=INF; MS0(vis); dist[1]=0; stack<int> s; s.push(1);vis[1]=1; while(!s.empty()) { int d=s.top();s.pop();vis[d]=0; for(Edge *p=e[d].next;p!=NULL;p=p->next) { if(relax(d,p->v,p->w)&&!vis[p->v]) { s.push(p->v); vis[p->v]=1; } } } } int main() { int u,v,N,M; ll w; MS0(e); scanf("%d%d",&N,&M); for(int i=0;i<M;i++) { scanf("%d%d%lld",&u,&v,&w); add_edge(u,v,w); } spfa(); printf("%d\n",dist[N]); return 0; }
----------------------------------好吧,因为未知原因,这个题一直WA,所以并没有AC,所以就没有AC代码了,羞耻的分割线----------------------------------
L POJ 2502 Subway
题意:在笛卡尔坐标系下给出家和学校的坐标,再给你几条地铁线,以及地铁线上的节点,你可以在任意节点上下地铁。地铁的速度是跑步速度的4倍,问你到学校最短的时间。
思路:建图的时候把地铁线上的距离缩短为1/4,然后求出最短路,再除以跑步速度,最后得到答案。
----------------------------------好吧,因为未知原因,这个题一直WA,所以并没有AC,所以就没有AC代码了,羞耻的分割线----------------------------------
M POJ 1062 昂贵的聘礼
题意:中文题意,就不解释了。
思路:把每一个物品作为一个节点,每有一种交换就连一条权值为优惠价格的边。然后枚举交换的起始阶级k,然后他可以在k到k+M的阶级之内交换。对于每次枚举,求出
由起点到任意节点的最短路大小再加上这种物品的价格,取最小值。输出所有枚举的最小值中最小的那个。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<set> #include<map> #include<string> #include<math.h> #include<cctype> #define ll long long #define maxn 1000100 #define INF (1<<29) using namespace std; int M,N,X,T,V; int cost[120][120]; int L[120]; int P[120]; int maxl,ans ; bool vis[120]; int dist[120]; int main() { //freopen("in.txt","r",stdin); for(int i=0;i<120;i++) for(int j=0;j<120;j++) cost[i][j]=INF; cin>>M>>N; for(int i=1;i<=N;i++) { cin>>P[i]>>L[i]>>X; maxl=max(maxl,L[i]); for(int j=0;j<X;j++) { cin>>T>>V; cost[i][T]=V; } } ans=P[1]; for(int k=(L[1]<=M?1:L[1]-M);k<=L[1];k++) { memset(vis,0,sizeof(vis)); for(int i=1;i<=N;i++) dist[i]=INF; dist[1]=0; while(1) { int v=-1; for(int u=1;u<=N;u++) if(!vis[u]&&(v==-1||dist[u]<dist[v])) v=u; if(v==-1) break; vis[v]=1; if(k<=L[v]&&L[v]<=min(k+M,maxl)) for(int u=1;u<=N;u++) if(k<=L[u]&&L[u]<=min(k+M,maxl)) dist[u]=min(dist[u],cost[v][u]+dist[v]); } for(int i=1;i<=N;i++) ans=min(ans,dist[i]+P[i]); } printf("%d\n",ans); }
Q HDU 3416 Marriage Match IV
题意:n个城市,m条边,询问互不相交的最短路有多少条。
思路:dijkstra+网络流,可以参考我网络流的题解。
标签:
原文地址:http://www.cnblogs.com/onlyAzha/p/4743660.html