UVA 10048 Audiophobia

题目链接  http://acm.hust.edu.cn/vjudge/problem/22156


从a点到b点, 找到一条路径,
使得这条路径上的所有噪音中最大的值是所有路径中最小的
求这个最小值

我是先弄出一个最小生成树 然后将图存起来
对于每个提问  都dfs一遍 将路径的权值存入path[] 
 当遍历到终点时 取path[]中的最大值 
 
其他思路:
还可以用Kruskal算法,按照Kruskal算法的步骤,一条边一条边的加入树中,
每加入一次,就判断所有要问的起点和终点是否已经连通,
 一旦有连通的,那么那条路径中的最大值便是当前加入的这条边的权值,
因为加入的边是按照从小到大顺序加入的。 


我的:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <string>
#include <map>
#include <set>
#define pi acos(-1)
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<int, int> P;
const int maxn = 1e5 + 5;

struct Road{
	int u, v, w;
}road[1005];
struct edge{
	int v, w;
	edge(int v_, int w_){
		v = v_; w = w_;
	}
};
int n, m, q, ans, fir = 1;
int ret[105], vis[105];
int path[105];
vector<edge>G[105];
int cmp(Road a, Road b)
{
	if (a.w < b.w) return 1;
	return 0;
}
int find(int a)
{
	if (ret[a] == -1) return a;
	return ret[a] = find(ret[a]);
}
void dfs(int u, int v, int k)
{
	if (u == v){
		for (int i = 1; i < k; i++)
			ans = max(ans, path[i]);
	}	
	vis[u] = 1;
	for (int i = 0; i < G[u].size(); i++){
		edge e =  G[u][i];
		if (!vis[e.v]){
			path[k] = e.w;
			dfs(e.v, v, k+1);
		}
	}
	vis[u] = 0;
}
int main(void)
{
//	freopen("C:\\Users\\wave\\Desktop\\NULL.exe\\NULL\\in.txt","r", stdin);
	int i, j, k, u, v, w, cas = 1;
	while (~scanf("%d %d %d", &n, &m, &q) && (n||m||q))
	{
		if (fir) fir = 0;
		else printf("\n");
		for (i = 1; i <= n; i++) G[i].clear();
		for (i = 1; i <= m; i++)
			scanf("%d %d %d", &road[i].u, &road[i].v, &road[i].w);
		memset(ret, -1, sizeof(ret));
		sort(road+1, road+1+m, cmp);
		for (i = 1; i <= m; i++){
			int x = find(road[i].u);
			int y = find(road[i].v);
			if (x == y) continue;
			G[road[i].u].push_back(edge(road[i].v,road[i].w));
			G[road[i].v].push_back(edge(road[i].u,road[i].w));
			ret[x] = y;
		}
		printf("Case #%d\n", cas++);
		for (i = 1; i <= q; i++){
			scanf("%d %d", &u, &v);
			int x = find(u);
			int y = find(v);
			if (x != y){
				printf("no path\n");
				continue;
			}
			memset(vis, 0, sizeof(vis));
			ans = -1;
			dfs(u, v, 1);
			printf("%d\n", ans);
		}
	}

	return 0;
}

其他思路:

#include<cstdio>  
#include<cstring>  
#include<algorithm>  
#define N 1005  
using namespace std;  
int n,m,Q, f[N],rank[N],ans[N*10];  
bool vis[N*10];  
  
struct Edge{  
    int u,v,val;  
    friend bool operator<(const Edge&a,const Edge&b){  
        return a.val < b.val;  
    }  
}arr[N];  
struct Query{  
    int id, u, v;  
}q[N*10];  
  
inline void init(){  
    for(int i=0; i<N; ++i)  
        f[i]=i,rank[i]=0;  
}  
int find(int x){  
    int i,j=x;  
    while(j!=f[j]) j=f[j];  
    while(x!=j){  
        i=f[x]; f[x]=j; x=i;  
    }  
    return j;  
}  
bool Union(int x, int y){  
    int a=find(x), b=find(y);  
    if(a==b)return false;  
    if(rank[a]>rank[b])  
        f[b]=a;  
    else{  
        if(rank[a]==rank[b])  
            ++rank[b];  
        f[a]=b;  
    }  
    return true;  
}  
      
  
int main(){  
    int a,b,c,cas=1;  
    while(~scanf("%d%d%d",&n,&m,&Q)){  
        if(!n&&!m&&!Q) break;  
        for(int i=0; i<m; ++i){  
            scanf("%d%d%d",&a,&b,&c);  
            arr[i].u=a, arr[i].v=b, arr[i].val=c;  
        }  
        for(int i=0; i<Q; ++i){  
            scanf("%d%d",&a,&b);  
            q[i].id=i, q[i].u=a, q[i].v=b;  
        }  
        init();  
        memset(vis, 0, sizeof(vis));  
        memset(ans, -1, sizeof(ans));  
        sort(arr,arr+m);  
        for(int i=0; i<m; ++i){  
            if(Union(arr[i].u,arr[i].v)){  
                for(int j=0; j<Q; ++j)if(!vis[j]){  
                    int a=find(q[j].u), b=find(q[j].v);  
                    if(a==b){  
                        vis[j] = true;  
                        ans[j] = arr[i].val;  
                    }  
                }  
            }  
        }  
        if(cas!=1) printf("\n");  
        printf("Case #%d\n", cas++);  
        for(int i=0; i<Q; ++i){  
            if(ans[i]==-1) printf("no path\n");  
            else printf("%d\n", ans[i]);  
        }  
    }  
    return 0;  
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值