您的位置:首页 > 运维架构

UVA 10048 - Audiophobia

2011-04-10 02:22 381 查看
题目大意:给出一个图,求某点到某点所必须忍受的最小噪音(即所经过路径的相邻两点的权的最大值最小)。

中文翻译

题目链接

题目类型:图论 / Floyd

 

题目分析:

①虽然做的是图论专题,但是开始还是觉得可以dp(后来证明我之前没有充分理解所谓“松弛技术”)。结果是写了一个可以过样例但是wa的dp。于是后来分析,关键点是两个相邻指标值,它们是相互依赖的,具体的说,假设有1点和2点它们相邻,则算d1的值时要根据d2的值算一次,但是d2的值也是要依赖d1的,所以这样解出来的不会是正确的结果。于是,我真正体会到了松弛技术(relax)的神奇之处。它可以把两个相互依赖的值慢慢收紧(得最小值)。

 

②Floyd。想到是Floyd的时候,算法便不难写出了。d[i][j]表示的是i点到j点要忍受的最小噪音,然后只需在松弛处稍作改动,把一般的          d[i][k]+d[k][j]换成max(d[i][k], d[k][j]),即d[i][j] = min(d[i][j], max(d[i][k], d[k][j])); 即可。

另外,“//if(d[i][k] < INF && d[k][j]<INF)    //加这个判断,可以解决INF相加可能溢出的问题.” 本来需要的,但是现在不是相加而是求max,所以可以不用判断。

 

代码:



错误的dp,贴出来引以为戒。(= =)

]#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define MAXN 102	//点
#define INF 1<<30
//#define MAXM 1002//边
vector<int> G[MAXN];
int w[MAXN][MAXN];
int d[MAXN], vis[MAXN];
inline int max(int x, int y) {return x>y? x: y;}
inline int min(int x, int y) {return x<y? x: y;}
int st, en;
int dp(int cur)
{
if(cur == st) return 0;		//停止条件
if(vis[cur] == 1) return d[cur];
vis[cur] = -1;		//正在访问
int ans = INF;
for(int i=0; i<(int)G[cur].size(); i++)
{
int u = cur, v = G[cur][i];
if(vis[v] == -1) continue;	//正在访问的不扩展
int t = max(dp(v), w[u][v]);
ans = min(t, ans);
}
vis[cur] = 1;
return d[cur] = ans;		//若ans最后还为INF,表示无法到达
}
int c, s, q;	//点,边,起终点对数
void clear()
{
for(int i=1; i<=c; i++)
if(!G[i].empty())
G[i].clear();
}
int read_graph()
{
int ok=1;
scanf("%d%d%d", &c, &s, &q);
if(!c && !s && !q) return 0;
for(int i=0; i<s; i++)
{
int c1, c2, di;
scanf("%d%d%d", &c1, &c2, &di);
G[c1].push_back(c2);
G[c2].push_back(c1);
w[c1][c2] = w[c2][c1] = di;
}
return 1;
}
int main()
{
int T=1;
while(read_graph())
{
if(T != 1) printf(" /n");	//case间 空行		//!各組測試資料間請輸出一空白列
printf("Case #%d/n", T++);
for(int i=0; i<q; i++)
{
memset(vis, 0, sizeof(vis));
scanf("%d%d", &st, &en);
int t = dp(en);
if(t == INF) printf("no path/n");
else printf("%d/n", t);		//
}
clear();
}
}




Floyd

]#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 102	//点
#define INF 1<<30
int d[MAXN][MAXN];			//!!
inline int max(int x, int y) {return x>y? x: y;}
inline int min(int x, int y) {return x<y? x: y;}
int st, en;
int c, s, q;	//点,边,起终点对数

void floyd()
{
for(int k=1; k<=c; k++)
for(int i=1; i<=c; i++)
for(int j=1; j<=c; j++)
//if(d[i][k] < INF && d[k][j]<INF)	//加这个判断,可以解决INF相加可能溢出的问题
d[i][j] = min(d[i][j], max(d[i][k], d[k][j]));		//!!
}
int read_graph()
{
scanf("%d%d%d", &c, &s, &q);
if(!c && !s && !q) return 0;
for(int i=1; i<=c; i++)
for(int j=1; j<=c; j++)
d[i][j] = i == j? 0: INF;
for(int i=0; i<s; i++)
{
int c1, c2, di;
scanf("%d%d%d", &c1, &c2, &di);
d[c1][c2] = d[c2][c1] = di;
}
return 1;
}
int main()
{
int T=1;
while(read_graph())
{
if(T != 1) printf("/n");	//case间 空行
printf("Case #%d/n", T++);
floyd();
for(int i=0; i<q; i++)
{
scanf("%d%d", &st, &en);
int t = d[st][en];
if(t == INF) printf("no path/n");
else printf("%d/n", t);
}
}
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  graph c 算法 扩展