POJ 2831 次小生成树

题意:给你n个点,m个遍,q次询问。问你改了第i条边的权值,他能否使得最小价格降低,或不变。


想法:是次小生成树的变形,很简单,但是我被prime恶心死了。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cassert>
#define inf 0x7fffffff
using namespace std;
const int nodes=1000+50;
const int edges=1000000+500;
int n,m,q;
int map[nodes][nodes];
struct node
{
	int u,v;
}e[edges];
int vis[nodes],pre[nodes];
int maxx[nodes][nodes];
int Min(int a,int b)
{
	if(a<b) return a;
	return b;
}
void Input()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j) map[i][j]=0;
			else map[i][j]=inf;
		}
	}
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		e[i].u=a;e[i].v=b;
		map[a][b]=map[b][a]=Min(map[a][b],c);
	}
} 
int Max(int a,int b)
{
	if(a>b) return a;
	return b;
}
void prime(){
      int i,j,t,loc;
      int dis[nodes];
      memset(vis,0,sizeof(vis));
      memset(maxx,0,sizeof(maxx));
      for(i=1;i<=n;i++){
         dis[i]=inf;
      }
      dis[1]=0;loc=1;vis[1]=1;
      for(i=1;i<n;i++){
         for(j=1;j<=n;j++){
             if(!vis[j]&&map[loc][j]<dis[j]){
                 dis[j]=map[loc][j],pre[j]=loc;
             }
         }
        int min=inf;
        for(j=1;j<=n;j++){
            if(!vis[j]&&dis[j]<min) min=dis[loc=j];
        }
        for(j=1;j<=n;j++) if(vis[j]){
            maxx[loc][j]=max(maxx[j][pre[loc]],dis[loc]);
            maxx[j][loc]=maxx[loc][j];
        }
         vis[loc]=1;
      }
}

void treatment()
{
	while(q--)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(b<=maxx[e[a].u][e[a].v]) printf("Yes\n");
		else printf("No\n");
	}
}
int main()
{
	while(~scanf("%d%d%d",&n,&m,&q))
	{
		Input();
		prime();
		treatment();
	}
	return 0;
} 


注意:vis的更新。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cassert>
#define inf 0x7fffffff
using namespace std;
const int nodes=1000+5;
const int edges=1000000+500;
int n,m,q;
int map[nodes][nodes];
struct node
{
	int u,v;
}e[edges];
int maxx[nodes][nodes];
int Min(int a,int b)
{
	if(a<b) return a;
	return b;
}
void Input()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j) map[i][j]=0;
			else map[i][j]=inf;
		}
	}
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		e[i].u=a;e[i].v=b;
		map[a][b]=map[b][a]=Min(map[a][b],c);
	}
} 
int Max(int a,int b)
{
	if(a>b) return a;
	return b;
}
void prime()
{
	memset(maxx,0,sizeof(maxx));
	int pre[nodes],low[nodes],vis[nodes];
	for(int i=1;i<=n;i++)
	{
		low[i]=map[1][i];
		pre[i]=1;
		vis[i]=0;
	}
	low[1]=0;
	vis[1]=1;
	pre[1]=-1;
	for(int i=2;i<=n;i++)
	{
		int minn=inf;
		int pos;
		for(int j=1;j<=n;j++)
		{
			if(!vis[j]&&minn>low[j])
			{
				minn=low[j];
				pos=j;
			}
		}
		vis[pos]=1;
		for(int j=1;j<=n;j++)
		{
			if(vis[j]&&j!=pos)
			{
				maxx[pos][j]=maxx[j][pos]=Max(maxx[j][pre[pos]],low[pos]);
			}
			if(!vis[j]&&low[j]>map[pos][j])
			{
				low[j]=map[pos][j];
				pre[j]=pos;
			}
		}
	}
}
void treatment()
{
	while(q--)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(b<=maxx[e[a].u][e[a].v]) printf("Yes\n");
		else printf("No\n");
	}
}
int main()
{
	while(~scanf("%d%d%d",&n,&m,&q))
	{
		Input();
		prime();
		treatment();
	}
	return 0;
} 


你可能感兴趣的:(POJ 2831 次小生成树)