Day4-T3
原题目
吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火。昨天,吉儿无意之中得到了散 落民间几百年的珍宝——月亮之眼。吉儿深知“月亮之眼”价值连城:它是由许多珍珠相连而成的,工 匠们用金线连接珍珠,每根金线连接两个珍珠;同时又对每根金线染上两种颜色,一半染成银白色,一 半染成黛黑色。由于吉儿自小熟读古籍,所以还晓得“月亮之眼”的神秘传说:“月亮之眼”原是一个 古代寺庙的宝物,原本是挂在佛堂的一根顶梁柱上的,整个宝物垂直悬挂,所有珍珠排成一线,且都镶嵌在柱子里,而每一根金线又都是绷紧的,并且金线的银白色一端始终在黛黑色一端的上方;然而,在 一个月圆之夜,“月亮之眼”突然从柱里飞出,掉落下来,宝物本身完好无损,只是僧侣们再也无法以 原样把“月亮之眼”嵌入柱子中了。吉儿望着这个神秘的宝物,回忆着童年读到的传说,顿时萌发出恢 复“月亮之眼”的冲动,但是摆弄了几天依旧没有成功。
为了把“月亮之眼”还原,吉尔拜访了 P 个僧侣,每个僧侣根据自己的回忆告诉给了一些有关的信 息,主要是描述某两个珍珠之间的距离。
例如根据回忆,1 号珍珠到 5 号珍珠的距离是 10,其中 1 号这头是银白色金线,5 号这头是黛黑色 金线。
你要设计一个程序,对于给定的“月亮之眼”进行周密分析,然后给出这串宝物几百年前嵌在佛堂 顶梁柱上的排列模样(各个珍珠在顶梁柱上的位置),珍珠的大小忽略不计。
第一行有两个整数 N 和 P,其中 N 表示宝物中的珍珠个数,P 表示有 P 个僧侣的句子,对金线的一些描述; 以下 P 行描述珍珠连接情况:第 i+1 行有三个整数,Ri1,Ri2,Li。其中 Ri1 表示第 i 根金线的银白色一 端连接的珍珠序号;Ri2 表示第 i 根金线的黛黑色一端连接的珍珠序号;Li 表示第 i 根金线的长度。
输出文件共 N 行: 第 i 行一个整数 S,它表示标号为 i 的珍珠在顶梁柱上距离最高位置珍珠的距离。
若无解则输出仅一行,包含一个整数“-1”。
S1:
Input:
9 9 1 2 3 2 3 5 2 7 1 4 5 4 5 6 1 5 9 1 6 7 1 7 8 3 9 8 4
Output:
2 5 10 0 4 5 6 9 5
Describe:图论,就是求权值
code:
#include<bits/stdc++.h> #define INF 214748364 #define eps 1e-9 #define rep1(a,b) for(register int i=(a);i<=(b);i++) #define rep2(a,b) for(register int j=(a);j<=(b);j++) using namespace std; long long dis[255][255],g,n,p,x,y,z; //dis[i][j]表示 i->j 的最短路 bool flg; inline int read(){ int ret=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();} while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar(); return ret*f; } inline double read2(){ double X=0,Y=1.0;int w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=X*10+(ch^48),ch=getchar(); ch=getchar(); while(isdigit(ch)) X+=(Y/=10)*(ch^48),ch=getchar(); return w?-X:X; } inline void Floyd(){ //Floyd for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) if(i!=j&&j!=k&&i!=k)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } inline void write(int x){ if(x<0){putchar('-');write(-x);return;} if(x/10) write(x/10); putchar(x%10+'0'); } int main(){ // freopen("mooneye.in","r",stdin); // freopen("mooneye.out","w",stdout); n=read(),p=read(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=0x7fffff,dis[i][i]=0; //memset for(int i=1;i<=p;i++)x=read(),y=read(),z=read(),dis[x][y]=z,dis[y][x]=-z; //建边及反建边 [值为负] Floyd(); for(int i=1;i<=n;i++){ flg=1; for(int j=1;j<=n;j++) if(dis[i][j]<0) //不在某一个点上,即非根节点 { flg=0; //退出循环 break; } if(flg)g=i; //存储根节点 } if(!g)cout<<-1,exit(0); //找不到根节点 for(int i=1;i<=n;i++)if(dis[g][i]==0x7fffff){cout<<-1;return 0;} //无边 for(int i=1;i<=n;i++)write(dis[g][i]),puts("");return 0; //输出 }