4681 bzoj

トピックリンク

問題の意味

無向グラフのエッジに権利があり、今行くのn番ポイントから1点は、あなたが右サイドk番目を交換することができますが尋ねたどのくらいの最短最短

データ範囲

n個 50 , m 150 , k 20 N \ 50メートル\ 150 K \ 20

ソリューション

最短:右側に数回交換し、私たちが知る必要があるすべての最初には、この点に行き、その後、今の状態の側面があります。ある時点で、今考えてみて、状態が必要以上何を計算。

まず十分に文書が、2番目は、私たちが第二の状態を記録することができ、とても扱いいくつかの制限を追加することを検討することは容易ではない。大量の注文に小さなサイド・バイ・サイド後の右側を、我々は最高のやり取りに列挙します使用前の記事リットル。このアプリケーションの順とインペリアルリットルのエッジが大に小さいです。

この状態遷移は考案することができる:DIS [U] [j]を[W] UはL jのエッジがWストリップのその交換、使用される前に、現在のドットが来る表します。

転写議論の3種類の
この側面は、我々は順番に制限による使用に行くために電流Iの前縁必要とされ、我々は最初に、J + 1と現在のこのエッジを置き換える縁であろう、しかし、このエッジは必須の使用であるので、交換の数を消費しないので

			if(id<=l){
				if(j<l&&dis[v][j+1][w]>dis[u][j][w]+a[j+1].c){
					dis[v][j+1][w]=dis[u][j][w]+a[j+1].c;
					if(!vis[v][j+1][w]){
						q.push(node(v,j+1,w));
						vis[v][j+1][w]=1; 
					}
				}
			}

2電流側がlの記事1側の前にこれを移動するための方法ではない、と我々はリットルの前縁にそれを置きます

				if(j<l&&w<k&&dis[v][j+1][w+1]>dis[u][j][w]+a[j+1].c){
					dis[v][j+1][w+1]=dis[u][j][w]+a[j+1].c;
					if(!vis[v][j+1][w+1]){
						q.push(node(v,j+1,w+1));
						vis[v][j+1][w+1]=1;
					}
				}

私たちは、この辺に直接行く3、交換しません

				if(dis[v][j][w]>dis[u][j][w]+e[i].w){
					dis[v][j][w]=dis[u][j][w]+e[i].w;
					if(!vis[v][j][w]){
						q.push(node(v,j,w));
						vis[v][j][w]=1;
					}
				}

統計必要が交換の回数を列挙するための最後の回答(ときに最もワット回のDIS配列の意味は短絡だけの交換であるため、ここでの交換は、必ずしもより多くの優れたではありません)

for(int i=0;i<=k;i++)ans=min(ans,dis[n][l][i]);

すべてのコード:

#include<bits/stdc++.h>
using namespace std;
const int maxn=155;
inline int read(){
	char c=getchar();int t=0,f=1;
	while((!isdigit(c))&&(c!=EOF)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)&&(c!=EOF)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
	return t*f;
}
int n,m,k;
struct node{
	int a,b,c;
	node(int aa=0,int bb=0,int cc=0){a=aa,b=bb,c=cc;}
}a[maxn];
struct edge{
	int v,p,w,id;
}e[maxn<<1];
int h[maxn],cnt;
inline void add(int a,int b,int c){
	e[++cnt].p=h[a];
	e[cnt].v=b;
	e[cnt].w=c;
	h[a]=cnt;
	e[++cnt].p=h[b];
	e[cnt].v=a;
	e[cnt].w=c;
	h[b]=cnt;
}
bool cmp(node a,node b){
	return a.c<b.c;
}
int ans=0x3f3f3f3f;
int dis[maxn][maxn][maxn];//第i个点,前l条边用了j条,路径上有k条边本来大于L,但是被换了 
typedef pair<int,int> pii;
queue<node> q;
int vis[maxn][maxn][maxn];
void dj(int l){
	memset(vis,0,sizeof(vis));
	memset(dis,0x3f,sizeof(dis));
	dis[1][0][0]=0;
	q.push(node(1,0,0));
	while(!q.empty()){
		node now=q.front();int u=now.a,j=now.b,w=now.c;q.pop();
		vis[u][j][w]=0;
		for(int i=h[u];i;i=e[i].p){
			int v=e[i].v,id=(i+1)/2;
			if(id<=l){
				if(j<l&&dis[v][j+1][w]>dis[u][j][w]+a[j+1].c){
					dis[v][j+1][w]=dis[u][j][w]+a[j+1].c;
					if(!vis[v][j+1][w]){
						q.push(node(v,j+1,w));
						vis[v][j+1][w]=1; 
					}
				}
			}
			else{
				if(j<l&&w<k&&dis[v][j+1][w+1]>dis[u][j][w]+a[j+1].c){
					dis[v][j+1][w+1]=dis[u][j][w]+a[j+1].c;
					if(!vis[v][j+1][w+1]){
						q.push(node(v,j+1,w+1));
						vis[v][j+1][w+1]=1;
					}
				}
				if(dis[v][j][w]>dis[u][j][w]+e[i].w){
					dis[v][j][w]=dis[u][j][w]+e[i].w;
					if(!vis[v][j][w]){
						q.push(node(v,j,w));
						vis[v][j][w]=1;
					}
				}
			}
		}
	}
	for(int i=0;i<=k;i++)ans=min(ans,dis[n][l][i]);
}
int main(){
//	freopen("2.in","r",stdin);
//	freopen("2b.out","w",stdout);
	n=read(),m=read(),k=read();
	for(int i=1;i<=m;i++){
		a[i].a=read(),a[i].b=read(),a[i].c=read();
	}
	sort(a+1,a+1+m,cmp);
	for(int i=1;i<=m;i++){
		add(a[i].a,a[i].b,a[i].c);
	}
	for(int l=0;l<=m;l++){
		dj(l);//其实是spfa
	//	printf("%d\n",ans);
	}
	printf("%d\n",ans);
	return 0;
}

公開された61元の記事 ウォンの賞賛1 ビュー943

おすすめ

転載: blog.csdn.net/wmhtxdy/article/details/103935780