/*
思路:(Dijkstra 算法)
从单源点st开始,在外集合当中寻找离最短路集合最近的在外集合当中的点 i 。逐层往外延伸,
延伸的同时需要不断更新从st到外集合 j 点距离dis[j].
如果从最短集合里面经过 i 点再到 j 点的距离比原来的dis[j]还要近的话,那就更新dis[ j ]。
该算法的时间复杂度是(n^2),空间复杂度为(n^2)
*/
#include<iostream>
using namespace std;
#define MDIS 1000000
int dis[110],map[110][110],vis[110];//map[i][j]表示从i点到j点的距离。若两点间无通路,则距离为无穷大,vis[i]则表示i点是否已经在最短集合当中,dis[i]表示i 点到源点的最短距离
int main()
{
int n,m,min,i,j,v,a,b,c;
while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0))
{
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) map[i][j]=MDIS;
for(i=0;i!=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
map[a][b]=c;
map[b][a]=c;
}
memset(vis,0,sizeof(vis));
vis[1]=1;
for(i=1;i<=n;i++) dis[i]=map[1][i];
for(i=1;i<n;i++)
{
//cout<<"good"<<endl;
min=MDIS;
for(j=1;j<=n;j++)
{
//cout<<"good"<<endl;
if(!vis[j]&&min>dis[j])//这里应该是j这个点没有放入最短集合当中
{
min=dis[j];
v=j;
}
}
vis[v]=1;
for(j=1;j<=n;j++)
{
//cout<<"good"<<endl;
if(!vis[j]&&dis[v]+map[v][j]<dis[j]) dis[j]=dis[v]+map[v][j];
}
}
printf("%d\n",dis[n]);
}
return 0;
}
Einbahnstrasse
#include <cstdio>
#include <cstring>
#include <cctype>
#include <map>
#include <string>
using namespace std;
const int N=110,INF=1000010;
int n,m,sz;
int g[N][N];
int q[1010];
map<string,int> mp;
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(g[i][j]>g[i][k]+g[k][j])
g[i][j]=g[i][k]+g[k][j];
}
int main()
{
int C=0,c;
while(scanf("%d%d%d",&n,&c,&m),n||m||c)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=(i==j?0:INF);
mp.clear(); sz=0;
for(int i=0;i<=c;i++)
{
char u[15];
scanf("%s",u);
if(mp[u]==0) mp[u]=++sz;
int t=mp[u];
q[i]=t;
}
for(int i=0;i<m;i++)
{
char u[15],v[15],w[15];
scanf("%s%s%s",u,w,v);
if(mp[u]==0) mp[u]=++sz;
if(mp[v]==0) mp[v]=++sz;
int uu=mp[u], vv=mp[v], ww;
sscanf(w+2,"%d",&ww);
if(w[strlen(w)-1]=='>' && ww<g[uu][vv]) g[uu][vv]=ww;
if(w[0]=='<' && ww<g[vv][uu]) g[vv][uu]=ww;
}
floyd();
int ans=0;
for(int i=1;i<=c;i++) ans+=g[1][q[i]]+g[q[i]][1];
printf("%d. %d\n",++C,ans);
}
return 0;
}
Here We Go(relians) Again
#include"stdio.h"
#include"string.h"
struct A
{
int total;
int dis;
int mem[6];
int len[6];
}E[444];
int MIN(int a,int b)
{
return a>b?b:a;
}
void SPFA(int s)
{
int k,key;
int hash[555];
int i;
int queue[888];
queue[0]=s;
key=1;
k=0;
memset(hash,0,sizeof(hash));
hash[s]=1;
while(k<key)
{
for(i=0;i<E[queue[k]].total;i++)
{
if(E[queue[k]].dis+E[queue[k]].len[i]<E[E[queue[k]].mem[i]].dis)
{
E[E[queue[k]].mem[i]].dis=E[queue[k]].dis+E[queue[k]].len[i];
if(!hash[E[queue[k]].mem[i]])
{
hash[E[queue[k]].mem[i]]=1;
queue[key++]=E[queue[k]].mem[i];
}
}
}
hash[queue[k++]]=0;
}
}
int main()
{
int n,m;
int n_temp;
int i,l;
int limit;
int temp;
int t1,t2;
char str[10];
while(scanf("%d%d",&n,&m),n||m)
{
temp=(n+1)*(m+1);
for(i=1;i<=temp;i++) {E[i].total=0;E[i].dis=11111111;}
n_temp=2*n+1;
for(i=0;i<n_temp;i++)
{
if(i%2) limit=m+1;
else limit=m;
for(l=0;l<limit;l++)
{
scanf("%d%s",&temp,str);
if(temp==0) continue;
temp=2520/temp;
if(i%2==0) {t1=(i/2)*(m+1)+l+1;t2=t1+1;}
else {t1=((i-1)/2)*(m+1)+l+1;t2=t1+m+1;}
if(str[0]=='*')
{
E[t1].mem[E[t1].total]=t2;
E[t1].len[E[t1].total++]=temp;
E[t2].mem[E[t2].total]=t1;
E[t2].len[E[t2].total++]=temp;
}
else if(str[0]=='v')
{
E[t1].mem[E[t1].total]=t2;
E[t1].len[E[t1].total++]=temp;
}
else if(str[0]=='^')
{
E[t2].mem[E[t2].total]=t1;
E[t2].len[E[t2].total++]=temp;
}
else if(str[0]=='>')
{
E[t1].mem[E[t1].total]=t2;
E[t1].len[E[t1].total++]=temp;
}
else if(str[0]=='<')
{
E[t2].mem[E[t2].total]=t1;
E[t2].len[E[t2].total++]=temp;
}
}
}
E[1].dis=0;
SPFA(1);
if(E[(n+1)*(m+1)].dis==11111111) printf("Holiday\n");
else printf("%d blips\n",E[(n+1)*(m+1)].dis);
}
return 0;
}
Bus System
#include<stdio.h>
#include<math.h>
#define maxint 0x7f7f7f7f7f7f7f7fLL
_int64 map[102][102], dis[102][102], dist(_int64), l[5], c[5], x[102];
int n, m;
void init(), floyd();
int main()
{
init();
return 0;
}
void init()
{
int cnum, i, j, k, a, b;
scanf("%d", &cnum);
for(k = 1; k <= cnum; ++k){
printf("Case %d:\n", k);
for(j = 1; j <= 4; ++j)
scanf("%I64d", &l[j]);
for(j = 1; j <= 4; ++j)
scanf("%I64d", &c[j]);
scanf("%d %d",&n, &m);
for(j = 1; j <= n; ++j)
scanf("%I64d", &x[j]);
for(i = 1; i <= n; ++i)
for(j = i + 1; j <= n; ++j)
dis[i][j] = dis[j][i] = dist(x[i] - x[j]);
floyd();
for(j = 1; j <= m; ++j){
scanf("%d %d",&a, &b);
if(dis[a][b] != maxint)
printf("The minimum cost between station %d and station %d is %I64d.\n",a, b, dis[a][b]);
else
printf("Station %d and station %d are not attainable.\n", a, b);
}
}
}
_int64 dist(_int64 t)
{
if(t < 0) t = -t;
if(t > 0 && t <=l[1])
return c[1];
if(t > l[1] && t <= l[2])
return c[2];
if(t > l[2] && t <= l[3])
return c[3];
if(t > l[3] && t <= l[4])
return c[4];
if(t > l[4])
return maxint;
}
void floyd()
{
int i, j, k;
for(k = 1; k <= n; ++k)
for(i = 1; i <= n; ++i)
for(j = 1; j <= n; ++j)
if(dis[i][k] != maxint && dis[k][j] != maxint && dis[i][j] > dis[i][k] + dis[k][j])
dis[i][j] = dis[i][k] + dis[k][j];
}
Transit search
#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#define N 5050
#define NN 105
#define M 10001
#define inf 0x7fffffff
int place[8]={5120,2560,1280,640,320,160,80,40};
int fx,fy;
int ex,ey;
int m,n;
struct bus_stop{
int x,y;
char ch[30];
}B[N];
vector<bus_stop> bus_line[NN];
struct node{
int next,v,w;
node(){};
node(int a,int b,int c){
next=a;v=b;w=c;
}
}E[M];
int head[NN],dis[NN],NE;
bool h[NN];
void init(){
NE=0;
memset(head,-1,sizeof(head));
}
void insert(int u,int v,int w){
E[NE]=node(head[u],v,w);
head[u]=NE++;
}
bool update(int u,int v,int w){
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
return true;
}
return false;
}
void spfa(int beg,int end){
queue<int> q;
memset(h,0,sizeof(h));
for(int i=0;i<=m+1;i++)
dis[i]=inf;
dis[beg]=0;
q.push(beg);
while(!q.empty()){
int u=q.front();
q.pop();
h[u]=0;
for(int i=head[u];i!=-1;i=E[i].next){
int v=E[i].v;
if(update(u,v,E[i].w)&&!h[v]){
h[v]=1;
q.push(v);
}
}
}
if(dis[end]==inf){
printf("take a taxi\n");
return;
}
printf("%d\n",dis[end]);
}
int find(char *p){
for(int i=0;i<n;i++)
if(strcmp(p,B[i].ch)==0)
return i;
}
bool find_bus(vector<bus_stop> p,vector<bus_stop> q){
for(int i=0;i<p.size();i++)
for(int j=0;j<q.size();j++)
if(strcmp(p[i].ch,q[j].ch)==0)
return true;
return false;
}
void trans(char *p,int &x,int &y){
x*=4;y*=4;
for(int i=0;i<8;i++){
if(p[i]=='1')
y+=place[i];
else if(p[i]=='2')
x+=place[i];
else if(p[i]=='3'){
x+=place[i];
y+=place[i];
}
}
}
double cal_dis(int fx,int fy,int ex,int ey){
double temp1=(fx*1.0-ex*1.0)*(fx*1.0-ex*1.0);
double temp2=(fy*1.0-ey*1.0)*(fy*1.0-ey*1.0);
return sqrt(temp1+temp2);
}
int main(void){
int t;
scanf("%d",&t);
while(t--){
char s[10],e[10];
scanf("%s%d%d",s,&fx,&fy);
scanf("%s%d%d",e,&ex,&ey);
trans(s,fx,fy);
trans(e,ex,ey);
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s",B[i].ch);
scanf("%d%d",&B[i].x,&B[i].y);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
char ch[30];
int k;
scanf("%d",&k);
bus_line[i].clear();
while(k--){
scanf("%s",ch);
int id=find(ch);
bus_line[i].push_back(B[id]);
}
}
if(cal_dis(fx,fy,ex,ey)<=2000.0){
printf("walk there\n");
continue;
}
int beg=0;
int end=m+1;
bool flag1,flag2;
flag1=flag2=0;
init();
for(int i=1;i<=m;i++)
for(int j=0;j<bus_line[i].size();j++){
double k1=cal_dis(fx,fy,bus_line[i][j].x,bus_line[i][j].y);
double k2=cal_dis(ex,ey,bus_line[i][j].x,bus_line[i][j].y);
if(k1<=1000.0){
flag1=true;
insert(beg,i,1);
}
if(k2<=1000.0){
flag2=true;
insert(i,end,0);
}
}
if(!flag1||!flag2){
printf("take a taxi\n");
continue;
}
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++)
if(find_bus(bus_line[i],bus_line[j])){
insert(i,j,1);
insert(j,i,1);
}
spfa(beg,end);
}
}
find the safest road
/*
SPFA
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,st,ed,front,rear;
double mat[1005][1005],dis[1005];
int v[1005],q[1000001];
void spfa()
{
int i,p;
while(front<rear)
{
p=q[front++];
v[p]=0;
for(i=0;i<n;i++)
{
if(mat[p][i]==0||p==i)
continue;
if(dis[p]*mat[p][i]>dis[i])
{
dis[i]=dis[p]*mat[p][i];
if(!v[i])
{
q[rear++]=i;
v[i]=1;
}
}
}
}
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%lf",&mat[i][j]);
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&st,&ed);
memset(v,0,sizeof(v));
memset(dis,0,sizeof(dis));
v[st-1]=1;
dis[st-1]=1;
front=0;
rear=1;
q[front]=st-1;
spfa();
if(dis[ed-1]!=0)
printf("%.3lf\n",dis[ed-1]);
else
printf("What a pity!\n");
}
}
return 0;
}
How Many Paths Are There
#include <cstdio>
#include <cstring>
using namespace std;
const int N=60;
int g[N][N],n,m;
int dis[N][2],cnt[N][2];
bool vis[N][2];
void dijkstra(int p)
{
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
memset(dis,-1,sizeof(dis));
dis[p][0]=0; cnt[p][0]=1;
for(int k=0;k<2*n;k++)
{
int x,y,min=-1;
for(int i=0;i<n;i++)
if(!vis[i][0] && dis[i][0]!=-1 && (min==-1 || dis[i][0]<min))
min=dis[x=i][y=0];
else if(!vis[i][1] && dis[i][1]!=-1 && (min==-1 || dis[i][1]<min))
min=dis[x=i][y=1];
if(min==-1) break;
vis[x][y]=true;
for(int v=0;v<n;v++) if(g[x][v]!=-1)
{
int tdis=min+g[x][v];
if(dis[v][0]==-1 || tdis<dis[v][0])
{
dis[v][1]=dis[v][0];
cnt[v][1]=cnt[v][0];
dis[v][0]=tdis;
cnt[v][0]=cnt[x][y];
}
else if(tdis==dis[v][0]) cnt[v][0]+=cnt[x][y];
else if(dis[v][1]==-1 || tdis<dis[v][1])
{
dis[v][1]=tdis;
cnt[v][1]=cnt[x][y];
}
else if(tdis==dis[v][1]) cnt[v][1]+=cnt[x][y];
}
}
}
int main()
{
int s,e;
while(~scanf("%d%d%d%d",&n,&m,&s,&e))
{
memset(g,-1,sizeof(g));
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(g[u][v]==-1 || w<g[u][v]) g[u][v]=w;
}
dijkstra(s);
printf("%d %d\n",dis[e][1],cnt[e][1]);
}
}
In Action
/*
题意:有n个基地,分别标号1..n,每个地点都有一定的能量,选择一些基地使得能量和大于总和的一半,当然这些选择的点是与0连通的。起点在编号为0的基地。
分析:第一步:求起点为0,到其他点的最短路,
第二步:01背包,cost[i] 为起点到 i 的最短路,weight[i] 为 i 的能量。
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#define MAXN 101
#define MAXV 10001
#define INF 0x3fffffff
using namespace std;
int dis[MAXN][MAXN],d[MAXV],cost[MAXN],weight[MAXN];
void floyd(int n)
{
int i,j,k;
for(k=0;k<=n;k++)
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
void ZeroOnePack(int n,int v)
{
int i,j;
memset(d,0,sizeof(d));
for(i=1;i<=n;i++)
for(j=v;j>=cost[i];j--)
d[j]=max(d[j],d[j-cost[i]]+weight[i]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int test,n,m,x,y,z,i;
scanf("%d",&test);
while(test--)
{
scanf("%d%d",&n,&m);
for(x=0;x<=n;x++)
for(y=0;y<=n;y++)
dis[x][y]=dis[y][x]=(x==y?0:INF);
for(i=0;i<m;i++)
{
scanf("%d %d %d",&x,&y,&z);
if(dis[x][y]>z)
dis[x][y]=dis[y][x]=z;
}
int sump=0;
for(i=1;i<=n;i++)
{
scanf("%d",&weight[i]);
sump+=weight[i];
}
sump=(sump>>1)+1;
floyd(n);
bool flag=false;
int sumv=0;
for(i=1;i<=n;i++)
{
cost[i]=dis[0][i];
if(cost[i]!=INF) sumv+=cost[i];
}
ZeroOnePack(n,sumv);
flag=false;
for(i=1;i<=sumv;i++)
{
if(d[i]>=sump)
{
printf("%d\n",i);
flag=true;
break;
}
}
if(!flag) printf("impossible\n");
}
return 0;
}