これは、正のソリューションとAC ......... emmmmmのほぼ5日間にドラッグ...........
事実は、癌の質問は(人間の涙の建設側に疑問をどのように多くの時間を知っていないとの)双方向側を構築しなければならないことを教えて
爆発の考え方伝送
顔のタイトル
これは、問題は最小カットです
話し:
図の2つの部分が切断されるように、図いくらかのエッジが、切断しました。片側のコストを削減することは、このエッジの右側で、最小コストを見つけます。
定理のもののようです。
図最小カット最短双対グラフであります
question1:神の馬は、デュアルグラフでありますか?それを食べますか?
もちろん違います
図はここでも、元のブロックは、点、それに直交するオリジナル組み込み側縁、右上隅に同じ、新しいST 2点の右側と左下隅、EEND(2つの放電点として使用されますソースとシンク、最短ランとして、どのコーナーホット)上で重要ではありません。
髪のためにEENDではなく、それを終了しているのですか?
彼らはC ++ 11に終わりが低下しますので、CE
彼は、例えば、あまりにも抽象的と言います
オリジナル:
デュアルグラフ:
アイデアは非常に単純ですが、コードは依然として非常に困難である(それは名誉のタイトルです)
私たちは、これらの数字を発見する方法を考えます
(実際には、単に数字)
巣の番号:
次に、我々は、サブ側はポイントを表す方法を話し合う(私たちは、双方向の側を構築しなければならないことに注意してください)
横方向のエッジ:
赤色は、行番号i、列番号jの上側の左側にあります
我々は、各エッジ(i、j)を上記と点以下の点を計算する、稜線番号を直接端縁EEND構造に、1であれば、エッジライン数がNである場合、建物側ST上の出発点、そうでない場合は、上側及び下側の構造(サイドノートバイ構築* 2)
表現のポイント:
上記の点SS = 2 *(I-1)*(M-1)+ J + 1。
次の点EE = SS-M + 1。
垂直側:
右のドット:SS = j個+(M-1)*(2 *(I-1)+1)+1。
左点:EE = SS-M。
しばらくj = 1のとき:STと右端の点でも
場合J = M:左側点もEEND
通常:ポイントでもポイントと左の右端
双方向側の構築に注意してください!!!(* 3)
斜辺:
斜め上方を指す:SS = 2 *(I-1)*(M-1)+ J + 1。
斜め下方点:EE = SS + M-1。
ここでは、STとEENDを検討する必要はありません
* 5内蔵し、双方向の側
スパイシーなダイクストラのように、再び建設側の実行を完了した後、
コード:
#include<cstdio> #include<cmath> #include<cstring> #include<queue> #include<algorithm> #define ll long long #define pa pair<int,int> using namespace std; inline int read() { char ch=getchar(),lst; int x=0; while(ch<'0'||ch>'9') { lst=ch; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }return ((lst=='-')?-x:x); } int n,m,st=1,eend,head[2000009],cnt,dis[2000009]; const int inf=214748364; bool vis[2000009]; struct Ed{ int to,nxt,dis; }edge[7000009]; void add(int fr,int to,int dis) { cnt++; edge[cnt].to=to; edge[cnt].dis=dis; edge[cnt].nxt=head[fr]; head[fr]=cnt; } void dij()//堆优化的dij { for(int i=1;i<=eend;i++) dis[i]=inf; dis[1]=0; priority_queue<pa,vector<pa>,greater<pa> > q; q.push(make_pair(0,1)); while(!q.empty()) { int now=q.top().second; q.pop(); if(vis[now])continue; vis[now]=1; for(int e=head[now];e;e=edge[e].nxt) { int v=edge[e].to,di=edge[e].dis; if(dis[now]+di<dis[v]) { dis[v]=dis[now]+di; q.push(make_pair(dis[v],v)); } } } } int main() { n=read();m=read(); eend=(n-1)*2*(m-1)+2; for(int i=1;i<=n;i++)//横边 { for(int j=1;j<=m-1;j++) { int dis=read(); int ss=2*(i-1)*(m-1)+j+1; int ee=ss-m+1; if(i==1) {add(ss,eend,dis);add(eend,ss,dis); continue;} if(i==n) {add(st,ee,dis);add(ee,st,dis); continue;} add(ss,ee,dis);add(ee,ss,dis); } }//竖边 for(int i=1;i<n;i++) { for(int j=1;j<=m;j++) { int dis=read(); int ss=j+(m-1)*(2*(i-1)+1)+1; int ee=ss-m; if(j==1) {add(st,ss,dis);add(ss,st,dis); continue;} if(j==m) {add(ee,eend,dis);add(eend,ee,dis); continue;} add(ee,ss,dis);add(ss,ee,dis); } }//斜边 for(int i=1;i<n;i++) { for(int j=1;j<m;j++) { int dis=read(); int ss=2*(i-1)*(m-1)+j+1; int ee=ss+m-1; add(ee,ss,dis); add(ss,ee,dis); } } dij(); printf("%d",dis[eend]); }