求做法证伪,玄关
查看原帖
求做法证伪,玄关
1394167
li00000000a楼主2025/6/21 11:21

如果我们只建立一个超级源点,这个点连接所有感兴趣的点的能一步直接到达的点,连接的边权大小与这些感兴趣的点和该点的边权大小相同,然后跑一遍dijskla,得到的对全图的最短路中在感兴趣的点中dis最小的 举个例子,样例的第二个中超级源点连接:点5边权10,点4边权2,点7边权3,点2边权6 这样感觉没什么问题,但写出的程序40分,并且题解里没有 Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,int> pli;
const int N=1e5+10;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n,m,k,T,lk[N];
vector<pii> G[N];
priority_queue<pli,vector<pli>,greater<pli> > pq;
bool vis[N];
ll dis[N];
void dijskla(){
	for(int i=1;i<=k;i++){
		for(auto v:G[lk[i]]){
			int x = v.second;
			dis[x] = min(dis[x],v.first*1ll);
			pq.push({v.first,v.second});
			//printf("len %lld to %d has been pushed.\n",v.first*1ll,v.second);
		}
	}
	//cout<<"\n"<<"\n";
	pli cur,nxt;
	while(!pq.empty()){
		cur = pq.top();
		//printf("len %lld to %d has been carried.\n",cur.first,cur.second);
		pq.pop();
		if(cur.first > dis[cur.second]){
			//printf("It's continued.\n");
			continue;
		} 
		vis[cur.second] = true;
		for(auto v:G[cur.second]){
			if(vis[v.second]) continue;
			int x = v.second;
			
			if(dis[x] > dis[cur.second]+v.first){
				dis[x] = dis[cur.second]+v.first;
				pq.push({dis[x],x});
				//printf("len %lld to %d has been pushed.\n",dis[x],x);
			}
		}
	}
}
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>m>>k;
		for(int i=1;i<=n;i++) G[i].clear();
		for(int i=1;i<=m;i++){
			int u,v,w;
			cin>>u>>v>>w;
			G[u].push_back({w,v});
		}
		
		memset(dis,inf,sizeof(dis));
		memset(vis,false,sizeof(vis));
		
		for(int i=1;i<=k;i++) cin>>lk[i];
		dijskla();
		ll ans = inf;
		for(int i=1;i<=k;i++) ans = min(ans,dis[lk[i]]);
		cout<<ans<<"\n";
	}
	return 0;
}

重要声明:这不是题解,因为Code没AC

2025/6/21 11:21
加载中...