标签:empty inf 最大的 push min turn out -- div
【POJ 2253 Frogger】
这道题求从u到v中所有通路的最大边最小
我直接二分做了,但实际上这种题是最短路算法的变种,意义在于告诉我们spfa这些算法不仅能维护出最短路,稍加修改后可以维护出很多其他东西。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<string> #include<stack> #include<fstream> #include<map> #include<iomanip> #include<algorithm> #include<vector> #define INF 2e9 #define maxnode 200000 #define ll long long #define lowbit(x) (x&(-x)) const int mod = 10007; const int MAXN = 2e2 + 10; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; using namespace std; struct node{ int v,d; node(int v1,int d1): v(v1),d(d1) {} }; vector<node> edges[MAXN]; int dist[MAXN],visit[MAXN],n; void spfa(){ for(int i=1;i<=n;i++) dist[i]=INF; dist[1]=0; visit[1]=1; queue<int> q; q.push(1); while( !q.empty() ){ int u = q.front(); q.pop(); visit[u]=0; for(int i=0;i<edges[u].size();i++){ int v = edges[u][i].v; if( dist[v]>dist[u]+edges[u][i].d ){ dist[v] = dist[u]+edges[u][i].d; if( !visit[v] ) q.push(v); } } } } int x[MAXN],y[MAXN]; double dis[MAXN][MAXN]; int main(){ //ios::sync_with_stdio(false); int tc=0; while(1){ scanf("%d",&n); if(n==0) break; for(int i=1;i<=n;i++) scanf("%d%d",x+i,y+i); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ double x1 = abs(x[i]-x[j]); double y1 = abs(y[i]-y[j]); dis[i][j] = sqrt(x1*x1 + y1*y1); //cout<<i<<" "<<j<<" "<<dis[i][j]<<endl; } } double start=0,end=3000,mid; while( end-start>=0.00001 ){ mid = (start+end)/2; for(int i=1;i<=n;i++) edges[i].clear(); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if( mid>=dis[i][j] ) edges[i].push_back( node(j,1) ); } } spfa(); if( dist[2]!=INF ) end=mid; else start=mid; } printf("Scenario #%d\n",++tc); printf("Frog Distance = %.3lf\n",end); printf("\n"); } return 0; }
【POJ 1797 Heavy Transportation】
维护所有通路的最小边最大
那修改后的松弛操作就是 dist[v] = max( dist[v], min( dist[u], edges[u][i].d ) )
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<string> #include<stack> #include<fstream> #include<map> #include<iomanip> #include<algorithm> #include<vector> #define INF 2e9 #define maxnode 200000 #define ll long long #define lowbit(x) (x&(-x)) const int mod = 10007; const int MAXN = 1e3 + 10; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; using namespace std; struct node{ int v,d; node(int v1,int d1): v(v1),d(d1) {} }; vector<node> edges[MAXN]; int dist[MAXN],visit[MAXN],n,m;//dist[i]代表从源点到i点中所有通路的最小边最大值 void spfa(){ for(int i=1;i<=n;i++) dist[i]=0; dist[1]=INF; visit[1]=1; queue<int> q; q.push(1); while( !q.empty() ){ int u = q.front(); q.pop(); visit[u]=0; for(int i=0;i<edges[u].size();i++){ int v = edges[u][i].v; int weight = min( edges[u][i].d,dist[u] );//weight是这条通路上的最小边 if( weight>dist[v] ){ dist[v] = weight; if( !visit[v] ) { //visit[v]=1; q.push(v); } } } } } //找所有通路中最小边最大的 int main(){ //ios::sync_with_stdio(false); int t,tc=0; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v,d; scanf("%d%d%d",&u,&v,&d); edges[u].push_back( node(v,d) ); edges[v].push_back( node(u,d) ); } spfa(); printf("Scenario #%d:\n",++tc); printf("%d\n",dist[n]); printf("\n"); for(int i=1;i<=n;i++) edges[i].clear(); } return 0; }
【POJ 3268 Silver Cow Party】
想到跑flyod但n^3太慢就t了,实际上反向建边跑两边spfa就可以了!
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<string> #include<stack> #include<fstream> #include<map> #include<iomanip> #include<algorithm> #include<vector> #define INF 2e9 #define maxnode 200000 #define ll long long #define lowbit(x) (x&(-x)) const int mod = 10007; const int MAXN = 1e3 + 10; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; using namespace std; struct node{ int v,d; node(int v1,int d1): v(v1),d(d1) {} }; vector<node> edges[MAXN]; int vis[MAXN],dist1[MAXN],dist2[MAXN],n,m,x; void spfa1(){ for(int i=1;i<=n;i++) dist1[i]=INF; queue<int> q; q.push(x); vis[x]=1; dist1[x]=0; while(!q.empty()){ int u = q.front(); q.pop(); vis[u]=0; for(int i=0;i<edges[u].size();i++){ int v = edges[u][i].v; int d = edges[u][i].d; if( dist1[u]+d<dist1[v] ){ dist1[v]=dist1[u]+d; if( !vis[v] ){ q.push(v); vis[v]=1; } } } } } void spfa2(){ for(int i=1;i<=n;i++) dist2[i]=INF; queue<int> q; q.push(x); vis[x]=1; dist2[x]=0; while(!q.empty()){ int u = q.front(); q.pop(); vis[u]=0; for(int i=0;i<edges[u].size();i++){ int v = edges[u][i].v; int d = edges[u][i].d; if( dist2[u]+d<dist2[v] ){ dist2[v]=dist2[u]+d; if( !vis[v] ){ q.push(v); vis[v]=1; } } } } } int u[100005],v[100005],d[100005]; int main(){ //ios::sync_with_stdio(false); while( scanf("%d%d%d",&n,&m,&x)!=EOF ){ for(int i=1;i<=m;i++){ scanf("%d%d%d",u+i,v+i,d+i); edges[ u[i] ].push_back( node(v[i],d[i]) ); } spfa1(); for(int i=1;i<=n;i++) edges[i].clear(); for(int i=1;i<=m;i++) edges[ v[i] ].push_back( node(u[i],d[i]) ); spfa2(); int ans=-1; for(int i=1;i<=n;i++){//枚举所有cows ans = max( ans,dist1[i]+dist2[i] ); } printf("%d\n",ans); for(int i=1;i<=n;i++) edges[i].clear(); } return 0; }
【】
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<string> #include<stack> #include<fstream> #include<map> #include<iomanip> #include<algorithm> #include<vector> #define INF 2e9 #define maxnode 200000 #define ll long long #define lowbit(x) (x&(-x)) const int mod = 10007; const int MAXN = 1e2 + 10; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; using namespace std; struct exchange{ int type; double r,c; exchange(int t1,double r1,double c1): type(t1),r(r1),c(c1) {} }; vector<exchange> edges[MAXN];//edges[i]是拿着i货币能选择的一些兑换方案 double d[MAXN],money; int n,m,s; struct node{ int type; double m;//状态是拿着m个type钱 node(int t1,double m1): type(t1),m(m1) {} }; bool bfs(){ for(int i=1;i<=n;i++) d[i]=-INF;//最优性剪枝,d[i]为i种货币最多有多少个 queue<node> q; q.push( node(s,money) ); d[s]=money; while( !q.empty() ){ node p = q.front(); q.pop(); if( p.type==s && p.m>money ) return true; for(int i=0;i<edges[p.type].size();i++){//能怎么换 exchange e = edges[p.type][i];//在这个所换 double m1 = (p.m-e.c)*e.r; if( m1>d[ e.type ] ){ d[e.type]=m1; q.push( node(e.type,m1) ); } } } return false; } int main(){ //ios::sync_with_stdio(false); while( scanf("%d%d%d%lf",&n,&m,&s,&money)!=EOF ){ for(int i=1;i<=m;i++){ int a,b; double r1,c1,r2,c2; scanf("%d%d%lf%lf%lf%lf",&a,&b,&r1,&c1,&r2,&c2); edges[a].push_back( exchange(b,r1,c1) ); edges[b].push_back( exchange(a,r2,c2) ); } if( bfs() ) printf("YES\n"); else printf("NO\n"); for(int i=1;i<=n;i++) edges[i].clear(); } return 0; }
标签:empty inf 最大的 push min turn out -- div
原文地址:https://www.cnblogs.com/ZhenghangHu/p/9869298.html