题解 P7297 【[USACO21JAN] Telephone G】 另类解法

一种新的方法,做法类似于 w33z 的毒瘤题,大家可以类比着看一下。

这道题启示我们什么?对于 \(n\) 个点向 \(m\) 个点分别连边,我们可以引入中介来讲 \(nm\) 条边变成 \(n+m\) 条边。

相似的道理,首先考虑如果 \(S_{i,i}\) 保证为 \(1\) 怎么做?我们可以将同一个种类的所有相邻两头奶牛的连边。每一个奶牛对于一种颜色,就只需要跟左边最近的和右边最近的连边就可以了(当然如果左边或右边没有这个种类的奶牛就自然不用了)。

我们回过来再考虑\(S_{i,i}\) 可能为 \(0\),也就是说不能再同种类的相邻的两头奶牛建边了。我们给每个点建一个虚点,虚点向这个点连边,我们就可以在同一个种类的所有相邻两头奶牛的虚点连边,每一个奶牛对于一种颜色,就只需要跟左边最近的和右边最近的虚点连边就可以了(当然如果左边或右边没有这个种类的奶牛就自然不用了)。

相比于分层图的解法,代码有些难写:

#include<bits/stdc++.h>
#define log(a) cerr<<"\033[32m[DEBUG] "<<#a<<'='<<(a)<<" @ line "<<__LINE__<<"\033[0m"<<endl
#define LL long long
#define eb emplace_back
#define SZ(x) ((int)x.size()-1)
#define ms(a,b) memset(a,b,sizeof a)
#define F(i,a,b) for(int i=(a);i<=(b);++i)
#define DF(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
inline int read(){char ch=getchar(); int w=1,c=0;
	for(;!isdigit(ch);ch=getchar()) if (ch=='-') w=-1;
	for(;isdigit(ch);ch=getchar()) c=(c<<1)+(c<<3)+(ch^48);
	return w*c;
}
const int N=1e5+10;
int b[N],cnt,lst[55][N],f[N];
bool h[55][55];
vector<pair<int,int> >v[N];
queue<int>q;
int main(){
	int n=read(),k=read();
	F(i,1,n){
		b[i]=read();
		v[i+n].eb(i,0);
		if(lst[b[i]][0]){
			v[i+n].eb(lst[b[i]][lst[b[i]][0]]+n,i-lst[b[i]][lst[b[i]][0]]);
			v[lst[b[i]][lst[b[i]][0]]+n].eb(i+n,i-lst[b[i]][lst[b[i]][0]]);
		}lst[b[i]][++lst[b[i]][0]]=i;
	}
	F(i,1,k)
		F(j,1,k){
			char ch=getchar();
			for(;ch!='0'&&ch!='1';ch=getchar());
			h[i][j]=(ch=='1');
		}
	F(i,1,n)
		F(j,1,k)
			if(h[b[i]][j]){
				if(!lst[j][0])continue;
				if(lst[j][1]<=i){
					int x=upper_bound(lst[j]+1,lst[j]+lst[j][0]+1,i)-lst[j]-1;
					v[i].eb(lst[j][x]+n,i-lst[j][x]);
				}
				if(lst[j][lst[j][0]]>i){
					int x=upper_bound(lst[j]+1,lst[j]+lst[j][0]+1,i)-lst[j];
					v[i].eb(lst[j][x]+n,lst[j][x]-i);
				}
			}
	ms(f,0x3f);f[1]=0;
	q.push(1);
	while(q.size()){
		int x=q.front();q.pop();
		for(auto[fi,se]:v[x]){
			if(f[x]+se<f[fi]){
				f[fi]=f[x]+se;
				q.push(fi);
			}
		}
	}
	if(f[n]==f[0])puts("-1");
	else cout<<f[n];
	return 0;
}
posted @ 2021-06-30 13:31  zhaohaikun  阅读(116)  评论(0)    收藏  举报