HDU 4522 (恶心建图)
湫湫系列故事——过年回家
Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1362 Accepted Submission(s): 320
Problem Description
出门在外,最想念的还是家,对在深圳腾讯工作的HR湫湫来说,春节回家是一年中最期盼的事,不仅可以见到阔别已久的亲人,还能以相亲的名义调侃众多帅哥(她的内心告诉她:如果相亲能遇到参加过腾讯编程马拉松的同学,就直接把自己嫁了~)。
同时,每年的春节湫秋也都会纠结一把,因为车票实在是太难抢了,不过2013的春节有点特殊,作为一个曾经的ACMer,湫湫制作出了很完美的刷票机,也就是说她再也不用担心买不上票了,但是想来想去还是觉得随便买票实在是浪费了辛辛苦苦搞出来的刷票机,所以她决定要用最舒适的方式回家。
假设湫湫有可能经过的n个城市分别编号从1到n,湫湫要从城市A回到城市B,购票网站上列出了t辆列车行程,每辆车的行程用一个字符串表示,途径的城市间用+号相连,如1+2+3+5代表一辆从1城市分别经过2,3到达5的火车,湫湫可以从中间任意一站出发和下车(路径是单向的,即必须沿字符串从左到右来走),每个字符串对应着一个整数k,k=0表示该车只有硬座,k=1表示该车有卧铺也有硬座,在整个回家的计划中,同一辆车可以坐无限次,为了中途换车的方便,如果在起点坐的是卧铺,则后面乘坐的车必须全是卧铺,同样的,如果在起点坐的是硬座,则后面乘坐的车必须全是硬座,假设一段(一辆车行程中,两相邻城市间为一段)硬座的不舒适度是D1,一段卧铺的不舒适度是D2,求湫湫回家最小的不舒适度。
同时,每年的春节湫秋也都会纠结一把,因为车票实在是太难抢了,不过2013的春节有点特殊,作为一个曾经的ACMer,湫湫制作出了很完美的刷票机,也就是说她再也不用担心买不上票了,但是想来想去还是觉得随便买票实在是浪费了辛辛苦苦搞出来的刷票机,所以她决定要用最舒适的方式回家。
假设湫湫有可能经过的n个城市分别编号从1到n,湫湫要从城市A回到城市B,购票网站上列出了t辆列车行程,每辆车的行程用一个字符串表示,途径的城市间用+号相连,如1+2+3+5代表一辆从1城市分别经过2,3到达5的火车,湫湫可以从中间任意一站出发和下车(路径是单向的,即必须沿字符串从左到右来走),每个字符串对应着一个整数k,k=0表示该车只有硬座,k=1表示该车有卧铺也有硬座,在整个回家的计划中,同一辆车可以坐无限次,为了中途换车的方便,如果在起点坐的是卧铺,则后面乘坐的车必须全是卧铺,同样的,如果在起点坐的是硬座,则后面乘坐的车必须全是硬座,假设一段(一辆车行程中,两相邻城市间为一段)硬座的不舒适度是D1,一段卧铺的不舒适度是D2,求湫湫回家最小的不舒适度。
Input
输入数据的第一行包含一个整数Q,表示测试数据的组数;
每组数据的第一行是2个正整数n和t,分别表示城市数和列车数;
接下来t行,每行一个字符串表示列车行程,字符串长度小于10000,每个字符串后跟一个整数k(k为0或1),之间用空格隔开;
接下来一行是D1,D2,其含义见题目描述;
最后一行是2个正整数A和B,表示起始和终点城市。
[Technical Specification]
1 <= Q <= 100
1 < n <= 200
1 < t <= 1000
0 < D1 <= 10000, 0 < D2 <= 10000,D1和D2的大小关系不确定
1 <= A, B <= n 且 A <> B
每组数据的第一行是2个正整数n和t,分别表示城市数和列车数;
接下来t行,每行一个字符串表示列车行程,字符串长度小于10000,每个字符串后跟一个整数k(k为0或1),之间用空格隔开;
接下来一行是D1,D2,其含义见题目描述;
最后一行是2个正整数A和B,表示起始和终点城市。
[Technical Specification]
1 <= Q <= 100
1 < n <= 200
1 < t <= 1000
0 < D1 <= 10000, 0 < D2 <= 10000,D1和D2的大小关系不确定
1 <= A, B <= n 且 A <> B
Output
对于每组数据,如果湫湫可以到达目的地,则输出一个整数,表示湫湫到家所需的最小不舒适度。如果不能到达则直接输出-1。
Sample Input
1
6 5
2+4+3+5+1+6 1
5+4+2+3+1 1
3+2+5+1+6 1
6+2 0
6+3+1+4+5+2 0
3 2
5 3
Sample Output
4
Source
又遇到字符串建图题目,上次就被坑= =数字有可能大于10,这样长度就不确定了切记啊c
然后直接dij就好了200个点不必堆优化即可
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define LL long long
#define ql(a,b) memset(a,b,sizeof(a))
int g1[205][205],g2[205][205];
LL D1,D2;
int d[205],n,vis[205];
int dij(int s,int e,int g[][205])
{
memset(d,inf,sizeof(d));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;++i) d[i]=g[s][i];
vis[s]=1;
for(int i=2;i<=n;++i){
int u=inf,minn=inf;
for(int j=1;j<=n;++j)
if(!vis[j]&&d[j]<minn) {minn=d[j];u=j;}
if(u==inf) break;
vis[u]=1;
for(int j=1;j<=n;++j){
if(!vis[j]&&g[u][j]!=inf){
if(d[j]>d[u]+g[u][j])
d[j]=d[u]+g[u][j];
}
}
}
return d[e];
}
int main()
{
int t,m,i,j,k;
char s[100005+15];
scanf("%d",&t);
while(t--){ql(g1,inf),ql(g2,inf);
scanf("%d %d",&n,&m);
for(i=1;i<=n;++i) g1[i][i]=g2[i][i]=0;
for(i=1;i<=m;++i){int temp=0,c; bool pd=0;
scanf(" %s %d",s,&k);
int szs=strlen(s);
if(szs<3) continue;
for(j=0;j<szs;j++){
if(isdigit(s[j])) temp=temp*10+s[j]-'0';
if(s[j]=='+'){
if(!pd) {c=temp;temp=0;pd=1;continue;}
else{ //cout<<c<<" "<<temp<<endl;
if(k==0) g1[c][temp]=1;
else g1[c][temp]=g2[c][temp]=1;
c=temp;
temp=0;
}
}
}
if(k==0) g1[c][temp]=1;
else g1[c][temp]=g2[c][temp]=1;
}
int S,E;
LL ans1=inf,ans2=inf;
scanf("%d %d",&D1,&D2);
scanf("%d %d",&S,&E);
ans1=min(ans1,(LL)dij(S,E,g1));
ans2=min(ans2,(LL)dij(S,E,g2));
if(ans1==inf&&ans2==inf) {puts("-1");continue;}
if(ans1==inf) printf("%lld\n",ans2*D2);
else if(ans2==inf) printf("%lld\n",ans1*D1);
else printf("%lld\n",min(ans1*D1,ans2*D2));
}
return 0;
}
using namespace std;
#define inf 0x3f3f3f3f
#define LL long long
#define ql(a,b) memset(a,b,sizeof(a))
int g1[205][205],g2[205][205];
LL D1,D2;
int d[205],n,vis[205];
int dij(int s,int e,int g[][205])
{
memset(d,inf,sizeof(d));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;++i) d[i]=g[s][i];
vis[s]=1;
for(int i=2;i<=n;++i){
int u=inf,minn=inf;
for(int j=1;j<=n;++j)
if(!vis[j]&&d[j]<minn) {minn=d[j];u=j;}
if(u==inf) break;
vis[u]=1;
for(int j=1;j<=n;++j){
if(!vis[j]&&g[u][j]!=inf){
if(d[j]>d[u]+g[u][j])
d[j]=d[u]+g[u][j];
}
}
}
return d[e];
}
int main()
{
int t,m,i,j,k;
char s[100005+15];
scanf("%d",&t);
while(t--){ql(g1,inf),ql(g2,inf);
scanf("%d %d",&n,&m);
for(i=1;i<=n;++i) g1[i][i]=g2[i][i]=0;
for(i=1;i<=m;++i){int temp=0,c; bool pd=0;
scanf(" %s %d",s,&k);
int szs=strlen(s);
if(szs<3) continue;
for(j=0;j<szs;j++){
if(isdigit(s[j])) temp=temp*10+s[j]-'0';
if(s[j]=='+'){
if(!pd) {c=temp;temp=0;pd=1;continue;}
else{ //cout<<c<<" "<<temp<<endl;
if(k==0) g1[c][temp]=1;
else g1[c][temp]=g2[c][temp]=1;
c=temp;
temp=0;
}
}
}
if(k==0) g1[c][temp]=1;
else g1[c][temp]=g2[c][temp]=1;
}
int S,E;
LL ans1=inf,ans2=inf;
scanf("%d %d",&D1,&D2);
scanf("%d %d",&S,&E);
ans1=min(ans1,(LL)dij(S,E,g1));
ans2=min(ans2,(LL)dij(S,E,g2));
if(ans1==inf&&ans2==inf) {puts("-1");continue;}
if(ans1==inf) printf("%lld\n",ans2*D2);
else if(ans2==inf) printf("%lld\n",ans1*D1);
else printf("%lld\n",min(ans1*D1,ans2*D2));
}
return 0;
}
对于上面的字符串处理也可以使用函数,例如strtok()
for(i=1;i<=m;++i){int temp=0,c; bool pd=0;
scanf(" %s %d",s,&k);
int szs=strlen(s);
if(szs<3) continue;
char *p;
p=strtok(s,"+");
while(p!=NULL){
int a=atoi(p);
p=strtok(NULL,"+");
int b=atoi(p);
if(p!=NULL) {
if(k==0) g1[a][b]=1;
else g1[a][b]=g2[a][b]=1;
}
}
}
scanf(" %s %d",s,&k);
int szs=strlen(s);
if(szs<3) continue;
char *p;
p=strtok(s,"+");
while(p!=NULL){
int a=atoi(p);
p=strtok(NULL,"+");
int b=atoi(p);
if(p!=NULL) {
if(k==0) g1[a][b]=1;
else g1[a][b]=g2[a][b]=1;
}
}
}