萌新妹子刚学OI 70分TLE求助/wq
查看原帖
萌新妹子刚学OI 70分TLE求助/wq
227728
冰糖鸽子「僕は…」楼主2021/8/4 11:43

RT,看前面的帖子应该是出问题的数据一样kk

但是没想出来怎么改进,下面的回复没看懂。从 nn 开始的 dfs 可以设 vis,但是从 11 开始的 dfs 有记录每个点到 11 的所有路径上的最小买入价值,那这样不就必须每个点都 dfs 到底吗yun

或者说可以改成用拓扑序每个点只遍历一次?但是怎么解决从 11 开始的限制啊yiw

码风良好有注释


// Problem: P1073 [NOIP2009 提高组] 最优贸易
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1073
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define M 100005
const int inf=1e9+7;
int n,m,U,V,o,cntp,ctp,ans,tf,t,vi[M];
int vis[M],fns[M],a[M],Buy[M];//Buy 为某个点到1的路径上的最小值
int sel[M],buy[M],in[M],frp[M];//sel是每个qltfl的最大值,buy是每个qltfl的最小值
//in是入度,frp是每个点来自哪个qltfl
vector<int>road[M],road2[M],rdd[M],rd[M],frd[M];
//road原图 road2反图 rdd每个连通分量的点集
//rd是新图,frd是新图的反图
map<pair<int,int>,int>app;//app[u,v]=1表示有一条u到v的边
queue<int>q;//拓扑用,代码里没用到
void dfs1(int x)//Kosaraju求qltfl,以下简称Ko,问题不在这里
{
	vis[x]=1;
	for(int i=0;i<road[x].size();i++)
	  if(!vis[road[x][i]])
	    dfs1(road[x][i]);
	fns[++cntp]=x;
}
void dfs2(int x)//Ko
{
	buy[cntp]=min(buy[cntp],a[x]);
	sel[cntp]=max(sel[cntp],a[x]);
	frp[x]=cntp,rdd[cntp].push_back(x);
	for(int i=0;i<road2[x].size();i++)
	  if(!frp[road2[x][i]])
	    dfs2(road2[x][i]);
}
void dfs(int x)//出问题的dfs,即从1开始遍历,同时记录路径中的最小值
{
	vi[x]=1;
	for(int i=0;i<rd[x].size();i++)
	{
		Buy[rd[x][i]]=min(Buy[rd[x][i]],min(buy[rd[x][i]],Buy[x]));
		dfs(rd[x][i]);
	}
}
void Dfs(int x)//从n开始遍历反图,这个很好改,问题也不在这里
{
	if(vi[x]) ans=max(ans,sel[x]-Buy[x]);
	for(int i=0;i<frd[x].size();i++)
	  Dfs(frd[x][i]);
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++) cin>>U>>V>>o,road[U].push_back(V),road2[V].push_back(U),(o==2?(road[V].push_back(U),road2[U].push_back(V)):road[0].push_back(0)); road[0].clear();
	for(int i=1;i<=n;i++) if(!vis[i]) dfs1(i); cntp=0; //Ko-1
	for(int i=n;i>=1;i--) if(!frp[fns[i]]) ++cntp,buy[cntp]=inf,sel[cntp]=-inf,dfs2(fns[i]); //Ko-2
	for(int i=1;i<=cntp;i++) {//建立新图
		for(int cc=0,j;cc<rdd[i].size();cc++) {
			j=rdd[i][cc];
			for(int dx=0;dx<road[j].size();dx++) {
				if(!app[make_pair(i,frp[road[j][dx]])]&&i!=frp[road[j][dx]])
				{
					app[make_pair(i,frp[road[j][dx]])]=1;
					frd[frp[road[j][dx]]].push_back(i);
					rd[i].push_back(frp[road[j][dx]]);
					in[frp[road[j][dx]]]++;
				} 
			}
		}
	}
	for(int i=1;i<=cntp;i++) Buy[i]=inf;//初始化
	Buy[frp[1]]=buy[1],dfs(frp[1]),Dfs(frp[n]);//出问题的一行
	cout<<ans<<endl;//输出答案
	return 0;
}
2021/8/4 11:43
加载中...