题目链接:https://codeforces.com/contest/1842/problem/D
借鉴:https://blog.csdn.net/Tanya_xiaomai/article/details/131393112
没看懂这个题
大意:丁真和他的n个动物朋友玩耍, 丁真非常喜欢他的1号朋友, 所以每次都要和1号朋友玩, 丁真不喜欢他的n号朋友, 所以丁真不和n号朋友玩
现在给出m个限制, 每个限制有u v w三个参数, 代表u号朋友和v号朋友不在一起的时间不超过w
(u和v同时都在和同时不在的时间不会被此条限制所影响)
丁真想尽可能用更多的时间和动物朋友们玩耍
请输出丁真最多能和动物朋友玩耍的时间和玩耍的次数
用二进制状态表示丁真和哪些动物朋友们玩耍, 并在同一行那一次输出玩耍了多久
其实是一个构造题,你需要构造一组满足最多玩耍时间的数据。满足约束
思路:首先1和n一定要在一个连通块中, 不一定需要1和n在一条边上但一定要在一个连通块中
因为无限的情况就是我们都一起玩就好了,然后单单不带n和它的连通块。因为只要有1就可以了。
相应的, 从1到n的最短路, 也就是此题中丁真最多能和动物朋友有玩的时间了。
这里就很抽象,最短路真是无奇不有。这里怎么考虑呢,因为只要我们存在绕路,就肯定会让某些点多进入一组游玩,这样就会破坏掉第三个的限制。
所以最短路就是最大满足的最大游玩时间。
每组数据通过贪心构造即可。
先构造最小的时间,然后在这个时间之前的我们都放进去就可以,每次游玩的时间,就是与上次游玩时间的之差。这里不难思考。
code:
void solve() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i!=j) a[i][j] = LNF; else a[i][j] = 0; } } int x,y,z; for(int i=1;i<=m;i++){ cin>>x>>y>>z; a[x][y] = a[y][x] = z; } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j] = min(a[i][k]+a[k][j],a[i][j]); //首先可以确定的是1和n必须在一个连通中。 //因为只有n存在绑定其他点,才可以利用n不属于S的限制从而有限。 if(a[1][n]>=LNF/2){ cout<<"inf"<<endl; return; } ll ans = a[1][n]; vector<ll> ve,d(n+1); for(int i=1;i<=n;i++){ d[i] = min(ans,a[i][n]);//能玩的最短的时间实际上就是组能玩的最短的时间。` ve.push_back(d[i]); } sort(ve.begin(),ve.end());//排个序去重,每次我们只取当前能玩的值减去上一轮,满足不一起的时间。 // for(auto c: ve) cout<<c<<' ';cout<<endl; ve.erase(unique(ve.begin(),ve.end()),ve.end()); cout<<ans<<' '<<ve.size()-1<<endl; ll ks = 0; for(int i=0;i<ve.size();i++){ if(!ve[i]) continue; for(int j=1;j<=n;j++){ cout<<(d[j]>=ve[i]);//可以满足的加进去 } cout<<' '<<ve[i]-ks<<endl;//之后的时间就是当前可以玩的减去之前不在一起的时间 ks = ve[i]; } }