最短路变形 最小边最大化 -- Heavy Transportation POJ - 1797

Heavy Transportation POJ - 1797

题意:
有n个城市,m条道路,在每条道路上有一个承载量,现在要求从1到n城市最大承载量,而一条路径的最大承载量是其中每条路的承载量的最小值。而最大承载量就是从城市1到城市n每条通路上的最小承载量的最大值

思路:
这道题目要求的是从1到N各个路径最小值的最大值,即d[y]=max(d[y],min(d[x],m[x][y]))。

/*
* Dijkstra 邻接矩阵
*/
#include 
#include 
#include 
#include 
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 1010;
const int inf = 1<<30;

int N, M, W[maxn][maxn];
int d[maxn];        //到达i点的最大最小值
bool used[maxn];
int dijkstra(){
    ms(used, 0);
    for(int i = 1; i <= N; i++)
        d[i] = W[1][i]; //初始化d
    used[1] = true;

    while(true){
        int u = 0, curMax = 0;
        for(int i = 1; i <= N; i++)
            if(!used[i] && d[i]>curMax)
                curMax = d[i], u = i;

        if(u == 0) break;
        used[u] = true;
        for(int v = 1; v <= N; v++)
            if(!used[v])
                d[v] = max(min(curMax, W[u][v]), d[v]);
    }
    return d[N];
}
int main()
{
    int T, u, v, w;
    cin >> T;
    for(int t = 1; t <= T; t++){
        ms(W, 0);
        cin >> N >> M;
        for(int i = 1; i <= M; i++){
            cin >> u >> v >> w;
            W[u][v] = W[v][u] = w;
        }

        cout << "Scenario #"<< t <<":" <<endl;
        cout << dijkstra() << endl << endl;
    }

	return 0;
}



/*
* Dijkstra 链式前向星
*/
#include 
#include 
#include 
#include 
using namespace std;

const int maxn = 1e5 + 10;
const int inf = 1e9 + 7;
int head[maxn], d[maxn];
bool vis[maxn];
int n, m, cnt;
struct node{
	int v, nex, len;
}edge[maxn];

void addedge(int u, int v, int len)
{
	edge[cnt].v = v;
	edge[cnt].nex = head[u];
	edge[cnt].len = len;
	head[u] = cnt++;
}

void dijkstra(int s)
{
	fill(d, d + maxn, inf);
	d[s] = 0;
	for(int i = 1; i <= n; i++) {
		int u = -1, MIN = inf;
		for(int j = 1; j <= n; j++) {
			if(vis[j] == false && d[j] < MIN) {
				u = j;
				MIN = d[j];
			}
		}
		vis[u] = true;
		for(int j = head[u]; j != -1; j = edge[j].nex) {
			int v = edge[j].v;
			if(vis[v] == false && d[u] + edge[j].len < d[v]) {
				d[v] = d[u] + edge[j].len;
			}
		}
	}
}

void init()
{
	memset(head, -1, sizeof(head));
}

int main()
{
	ios::sync_with_stdio(false);
	init();
	int s, t;
	cin >> n >> m >> s >> t;
	int x, y, z;
	for(int i = 1; i <= m; i++) {
		cin >> x >> y >> z;
		addedge(x, y, z);
		addedge(y, x, z);
	}
	dijkstra(s);
	cout << d[t] << endl;
	return 0;
}




/*
spfa邻接矩阵
4156K 469MS 
*/
#include 
#include 
using namespace std;
#define MAXV 1010
#define min(a,b) (a
 
int map[MAXV][MAXV],n,m;
 
int spfa(){
	queue <int>q;
	int i,j,v;
	int vis[MAXV],d[MAXV];
	for(i=1;i<=n;i++){
		vis[i]=0;
		d[i]=0;
	}
	q.push(1);
	vis[1]=1;
	while(!q.empty()){
		v=q.front();q.pop();
		vis[v]=0;
 
		for(i=1;i<=n;i++){
			if(v==1 && map[v][i]){
				d[i]=map[v][i];
				q.push(i);
				vis[i]=1;
				continue;
			}
			if(d[i]<min(d[v],map[v][i])){
				d[i]=min(d[v],map[v][i]);
				if(!vis[i]){
					vis[i]=1;
					q.push(i);
				}
			}
		}
	}
	return d[n];
}
 
int main(){
	int t,i,j,sum,a,b,c;
	scanf("%d",&sum);
	for(t=1;t<=sum;t++){
		scanf("%d%d",&n,&m);
		for(i=0;i<=n;i++)
			for(j=0;j<=n;j++)
				map[i][j]=0;
		for(i=1;i<=m;i++){
			scanf("%d%d%d",&a,&b,&c);
			map[a][b]=map[b][a]=c;
		}
		printf("Scenario #%d:\n",t);
		printf("%d\n\n",spfa());
	}
	return 0;
}





/*
spfa链式前向星
4156K 469MS 
*/
#include
#include
#include
#include
#include
using namespace std;
const int manx=1e6+5;
const int mamx=1e6+5;
int head[manx],d[manx];
bool vis[manx];
struct node{
    int v,w,next;
}a[mamx];
int n,m,s,e,k=0;
void add(int u,int v,int w)
{
    a[++k].next=head[u];
    a[k].w=w;
    a[k].v=v;
    head[u]=k;
}
void spfa()
{
    memset(d,0,sizeof(d));
    memset(vis,0,sizeof(vis));
    d[s]=1e9;
    queue<int>q;
    q.push(s);
    while(q.size())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i;i=a[i].next)
        {
            int v=a[i].v,w=a[i].w;
            if(d[v]<min(d[u],w)) {
                    d[v]=min(d[u],w);
                    if(!vis[v])
                        q.push(v),vis[v]=1;
            }
        }
    }
}
int main()
{
    int t;
    cin>>t;
    for(int o=1;o<=t;o++)
    {
        scanf("%d%d",&n,&m);
        s=1,e=n,k=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        spfa();
        printf("Scenario #%d:\n",o);
        printf("%d\n",d[e]);
        printf("\n");
    }
    return 0;
}


/*
*  dijkstra 优先队列 链式前向星优化
*/

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1005, M = 200005, INF = 0x3f3f3f3f;
int t, n, m, u, v, w, len, h[N], d[N];//d[i]代表1到i的路径中的最小值中的最大一个 
bool vis[N];
struct E {
	int v, w, next;
} e[M];
struct Node {
	int v, d;
	Node(int d, int v): d(d), v(v){}
	bool operator < (const Node&w) const {
		return d < w.d;//d大的应该先出来 
	}
};
void add(int u, int v, int w) {
	e[len].v = v;
	e[len].next = h[u];
	e[len].w = w;
	h[u] = len++;
}
void djkstra() {
	memset(vis, false, sizeof(vis));
	memset(d, 0, sizeof(d));
	d[1] = INF; //第一个点应该是无穷大 
	priority_queue<Node> q;
	q.push(Node(0, 1)); 
	while (!q.empty()) {
		int u = q.top().v;
		q.pop();
		if (vis[u]) continue;
		vis[u] = true;
		for (int j = h[u]; j; j = e[j].next) {
			int v = e[j].v;
			int w = min(d[u], e[j].w); //看这条边 和之前的最小值谁小
			if (d[v] < w) {
				d[v] = w;
				q.push(Node(d[v], v)); 
			} 
		} 
	}
}
int main() {
	scanf("%d", &t);
	for (int cas = 1; cas <= t; cas++) {
		memset(h, 0, sizeof(h)), len = 1;
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= m; i++) {
			scanf("%d%d%d", &u, &v, &w);
			add(u, v, w); add(v, u, w);
		} 
		djkstra();
		printf("Scenario #%d:\n%d\n\n", cas, d[n]);
	} 
	return 0;
} 


你可能感兴趣的:(图论)