[CF1842D] Tenzing and His Animal Friends

[CF1842D] Tenzing and His Animal Friends

Description

Tenzing 有 \(n\) 个朋友,每次举办聚会可以邀请一些朋友,有如下限制:

  • \(1\) 必须参加,\(n\) 不能参加。
  • \(m\) 条限制 \((u, v, w)\),表示 \(u\)\(v\) 中只有一个在聚会中的总时间不超过 \(w\)

最大化聚会总时间,并给出相应方案,即给出总聚会时间,每次聚会给出参与聚会的人和单次聚会时长。

Solution

我们考虑建图做法,首先我们可以把限制 \((u, v, w)\) 建边,而后我们考虑因为 \(n\) 不能参加聚会,所以 $u\to n $ 也有相应限制,我们考虑类似从 \(n\) 开始扩散的做法,即 \(u\)\(w\) 时刻前必须从 \(n\) 走到 \(u\),因而这样向前推可以得任何点必须在他的父节点等待 \(w_i\) 时刻前被到达,因而对于整张图考虑即相应总聚会时间最大值为 \(1\to n\) 的最短路。考虑将 \(n\) 作为起点用迪杰斯特拉算法跑最短路。不合法状态即 \(1\to n\) 最短路为极大值。

而后我们考虑构造,对于任何一个点 \(i\) 他的状态取决于当前的 \(dis_i\) 是否大于 0,大于 0 则状态为 1,反之为 0。我们考虑枚举一个时刻 \(T\)\(T’=\min ({dis_k},k\in{u})\),则在从当前时刻过渡到这个时刻所有点的 \(dis\) 均被去掉 \(T\),因而将这个时刻和所有点的状态存进 vector 中维护即可。当 \(dis_1\) 为 0 时结束更新答案。

Code

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int inf=4557430888798830398;
const int N=5e5+7;
vector<pair<int,int> > G[N];
int dis[N<<2];
bool _vis[N<<2];
int n,m,k;
int a[N];
//const int inf=1e9;

struct node{
	int dis,id;
	friend bool operator < (node a,node b){
		return a.dis>b.dis;
	}
};

void Dj(int s){
	memset(_vis,0,sizeof _vis);
	priority_queue<node> q;
	memset(dis,0x3f,sizeof dis);
	dis[s]=0;
  q.push({0,s});
	while(!q.empty()){
		int u=q.top().id;
		q.pop();
		if(_vis[u]) continue;
		_vis[u]=1;
		for(auto i:G[u]){
			int k=i.first,w=i.second;
			if(dis[k]>dis[u]+w){
				dis[k]=dis[u]+w;
				q.push({dis[k],k});
			}
		}
	}
}

struct node2 {
    int sta[110],t;
};

vector<node2> ans;

signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v,w;scanf("%lld%lld%lld",&u,&v,&w);
		G[u].push_back(make_pair(v,w)),G[v].push_back(make_pair(u,w));
	}
	Dj(n);
	if(dis[1]>=inf) return printf("inf"),0;
	printf("%lld ",dis[1]);
  while(dis[1]!=0){
	  int _min=inf;
		for(int i=1;i<=n;i++) if(dis[i]>0&&dis[i]<_min) _min=dis[i];
		node2 a;
		for(int i=1;i<=n;i++) a.sta[i]=dis[i]>0;
		a.t=_min;
		ans.push_back(a);
		for(int i=1;i<=n;i++) dis[i]-=_min;
	}
	printf("%lld\n",ans.size());
	for(auto it:ans){
	  for(int i=1;i<=n;i++){
			printf("%lld",it.sta[i]);
		}
	  printf(" %lld\n",it.t); 
	}
  return 0;
}
posted @ 2023-07-25 14:20  Zimo_666  阅读(42)  评论(0编辑  收藏  举报