[NOIPシミュレーションテスト]:トレンチゲーム(コストフロー)

タイトル説明

インターネットで$ NYG $は、ゲームの「ナイフ$ 999 $レベル」と呼ばれる場所に広告を誘致することです。
$ Nプロット点と$ M $チェックポイント、プロット点から別のプロット点につながるチェックポイント番目$のゲーム合計。
Xinshoucunと呼ばれる一つのプロット点。新しい村に通じるんが、チェックポイントは、物語は、サイクルを形成しません。(有向非巡回グラフの$ルートノードに実際に$ 1)。
$プロット点は、「エンドポイント」と呼ばれる$ sの、ゲームに代わって非常に高貴$ NYG $ので、我々は、ポイントからこの話を終了することができますので、彼は試合から、つまり(クリアランス考えることができる少なくとも$ K $回再生されるように感じましたの$ K $回)の終点に来Xinshoucun。$ NYG $充電電流として、当然のことながら、柔らかい姉妹通貨クリアランスにこのゲームをリフレッシュ(または彼の高貴なアイデンティティを満たすためにどのように?)各レベルのモンスターは$ NYG $によって、このチェックポイント通過を表す値を持っていますソフト姉妹コインの数は、当然のことながら、モンスターを倒すために、より多くの強力な、最初の$のx $回の死に更新されますする必要はモンスターが$ A_ix + B_i $柔らかい姉妹通貨でなく、自尊心のモンスター、$ C_I $のモンスターを必要とします時間は$お金だったとき$ NYGは、彼がこの関門を通過することはできません$ NYG $で、その結果、非表示にします殺しました。
$ NYG $が、彼は少なくとも(もちろん、お金のああを保存しない)を取得するために銀行から統一する必要がありますどのように多くのソフト姉妹通貨クリアランスを疑問に思い、彼はあなたによって解決することが厳選。


入力形式

最初の行は、4個の数の$ N、M、K、S含ま $ $ $ n番目のプロット点を発現し、$ M $、$ $ Sは$を含む次の行の終点を$、ゲームをプレイするために$ k回チェックポイントを数秒$、$ S $のエンドポイント数の代表。
5正の整数の$ X_I、Y_Iの次$ M $行、a_iを、B_i 、C_I $、 $ I $はX_I $ $ $号プロット点がプロット点の数Y_I $、$ a_iをに接続されているから、レベルの数を表します。 、タイトルとしてB_i、C_I $の重要性について説明します。


出力フォーマット

クリアランスは必要最低限​​の宗派ソフト妹を表す整数、$ $ -1出力そうでない場合は出力されていない場合。


サンプル

サンプル入力:

6 8 2 2
4 5
1 2 4 0 2
1 3 5 0 2
3 4 1 5 1
2 5 1 0 1
4 6 4 2 2
5 6 0 4 2
1 5 9 2
2 6 4 5 2

出力例:

16


データ範囲とヒント

サンプルは説明しました:

$ 5の第1の$ 1-> 2 - > $ 5、$コストから。
第二に$ 1-から> 3 - > $ 4 $ 11の$コスト。

データ範囲:

$ 30 \%の$のデータについては、$ a_iを= 0 $。
追加データ$ 20 \%の$のために、ゲームが鎖です。
$ \ 100%の$データ、$ 1 \ためleqslant N \ leqslant 1,000,1 \ leqslant M \ leqslant 20,000,1 \ leqslant K \ leqslant 200、a_iを、B_i \ geqslant 0,1 \ leqslant C_I \ leqslant K $。
$ int型の$の範囲でその答えを確保するために。


問題の解決策

メモのみ$ K $ 200が、コストがそれを流していると思っているでしょうか?

実際には、私の思考と問題解決若干のずれ。

記録の$ A、B $は、一度の支出の増加を手放すとき側の上に構築されたときにオフ以上の逆流がうまく、欠点はあなただけストリーミングできるということである、またはあなたが最良の答えを逃すことができます。

時間複雑:$ \シータ(メートルの\倍のk + N \倍のk ^ 2)$。

期待はスコア:$ $ 100ポイントを。

実際のスコア:$ $ 100ポイント。


コードの時間

#include<bits/stdc++.h>
using namespace std;
struct rec
{
	int nxt;
	int to;
	int w;
	int f;
	int a;
}e[100001];
int head[5001],cnt=1;
int n,m,k,s;
int S,T;
int que[100001],pre[50001],dis[50001];
bool vis[50001];
int ans;
void add(int x,int y,int w,int f,int a)
{
	e[++cnt].nxt=head[x];
	e[cnt].to=y;
	e[cnt].w=w;
	e[cnt].f=f;
	e[cnt].a=a;
	head[x]=cnt;
}
bool bfs()
{
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[S]=0;
	vis[S]=1;
	int he=1,ta=1;
	que[ta]=S;
	while(he<=ta)
	{
		for(int i=head[que[he]];i;i=e[i].nxt)
			if(e[i].w&&dis[que[he]]+e[i].f<dis[e[i].to])
			{
				dis[e[i].to]=dis[que[he]]+e[i].f;
				pre[e[i].to]=i;
				if(!vis[e[i].to])
				{
					vis[e[i].to]=1;
					que[++ta]=e[i].to;
				}
			}
		vis[que[he]]=0;
		he++;
	}
	return dis[T]!=1061109567;
}
void update()
{
	int flag=T;
	while(flag!=S)
	{
		int x=pre[flag];
		ans+=e[x].f;
		e[x].w--;
		e[x^1].w++;
		e[x].f+=e[x].a;
		e[x^1].f-=e[x].a;
		flag=e[x^1].to;
	}
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&k,&s);
	S=n+1,T=n+2;
	add(S,1,k,0,0);
	add(1,S,0,0,0);
	for(int i=1;i<=s;i++)
	{
		int x;
		scanf("%d",&x);
		add(x,T,k,0,0);
		add(T,x,0,0,0);
	}
	for(int i=1;i<=m;i++)
	{
		int x,y,a,b,c;
		scanf("%d%d%d%d%d",&x,&y,&a,&b,&c);
		add(x,y,c,b+a,a);
		add(y,x,0,-b,a);
	}
	cnt=0;
	while(bfs())
	{
		update();
		cnt++;
	}
	if(cnt<k)puts("-1");
	else printf("%d",ans);
	return 0;
}

rp++

おすすめ

転載: www.cnblogs.com/wzc521/p/11447008.html