NOIP冲刺(大水题专练)NOIP2009最优贸易

以前帮初学的脑洞过这个题

实际上还是多有趣的

问题是这样子的:

你需要买一次(所以这和APIO那个没什么关系)

定义dS为到目前为止从起点到现在最小值

dT为从这里到终点最小值

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
struct Front_star{
	int u,v,nxt;
}e[N*4];
int cnt=1;
int first[N]={};
void add(int u,int v){
	cnt++;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].nxt=first[u];
	first[u]=cnt;
}
int n,m;
queue<int> Q;
int dS[N]={};
int dT[N]={};
int vis[N]={};
int val[N]={};
int edge[N][3]={};
//int d1[N]={};
inline void SPFA(){
	Q.push(1);
	memset(dS,0x3f,sizeof(dS));
	while(!Q.empty()){
		int x=Q.front();
		Q.pop();
		vis[x]=0;
		for(int i=first[x];i;i=e[i].nxt){
			int v=e[i].v;
			if(dS[v]>min(dS[x],val[v])){
				dS[v]=min(dS[x],val[v]);
				if(!vis[v])
					Q.push(v),vis[v]=1;
			}
		}
	}
}
inline void SPFA2(){
	Q.push(n);
	memset(dT,-1,sizeof(dT));
	while(!Q.empty()){
		int x=Q.front();
		Q.pop();
		vis[x]=0;
		for(int i=first[x];i;i=e[i].nxt){
			int v=e[i].v;
			if(dT[v]<max(dT[x],val[v])){
				dT[v]=max(dT[x],val[v]);
				if(!vis[v])
					Q.push(v),vis[v]=1;
			}
		}
	}
}
int main(){
	read(n);
	read(m);
	for(int i=1;i<=n;i++){
		read(val[i]);
//		dS[i]=dT[i]=val[i];
	}
	for(int i=1;i<=m;i++){
		int x,y,z;
		read(x);
		read(y);
		read(z);
		edge[i][0]=x;
		edge[i][1]=y;
		edge[i][2]=z;
		add(x,y);
		if(z==2) 
			add(y,x);
	}
	SPFA();
//	cout<<dS[3]<<'\n';
	memset(vis,0,sizeof(vis));
	memset(first,0,sizeof(first));
	cnt=1;
	for(int i=1;i<=m;i++){
		add(edge[i][1],edge[i][0]);
		if(edge[i][2]==2)add(edge[i][0],edge[i][1]);
	}
	SPFA2();
	int ans=0;
	for(int i=1;i<=n;i++){
		ans=max(ans,dT[i]-dS[i]);
	}
	cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/fcb_x/article/details/80960754