題意: 首先有n個點, 然後每個點都乙個權值ai表示這個點上的士兵數量,如果ai為0則表示這個點是敵人的, 如果大於零則表示這個點是自己的並且有ai個士兵, 現在你只有一次機會可以移動所有的士兵, 注意 每個士兵只能移動一次, 並且只有兩種選擇, 要麼不動, 要麼移動到相鄰的乙個單位處的的自己的點上, 並且自己的點在移動完之後至少要存在一名士兵。 另外再輸入乙個n * n的字元矩陣, 如果s【i】【j】 為y則i, j相鄰, 並且 i, i永遠為n; 好了, 現在要求出 當敵人的點的相鄰自己點上的士兵都達到最大值的時候, 自己的電商的士兵數量最小的點的士兵數量是多少。
思路: 乙個很nice的思路, 我也是看到了題解之後才恍然大悟, 首先你要求最大的最小, 第一反應肯定是二分。但是之後又會想 二分怎麼分上下呢。。。這就很尷尬了。 我開始看這個題的時候根本沒想到網路流。。。。。然後想了一段時間也沒想出來就看了題解, 二分是對了, 分上下界的時候要用的網路流, 建圖的思想就是把這些點分開, 因為不是自己的點不能放士兵, 所以我們不管這些點, 然後我們把剩下自己的點分成和不是自己的點相鄰的點和僅與自己的點相鄰的點, 其次我們把每個點分成i和i', 首先i連源點流量為a[i], 然後i和i'連, 流量為a[i], i』是要連匯點的所以這樣可以保證連完圖之後士兵只走一次, 然後因為是自己的點, 所以每個點都可以給予相鄰的自己點的流量, 假如i跟j相鄰, i,j都是自己的點, 那麼連i到j『流量為a[i], 這很好理解, i點自己的士兵可以走到j點, 因為士兵只能走一次, 所以i只能給j自己點上的士兵, 之後連匯點就有區別了, 如果這個點和敵人的點相鄰, 那麼這個i』連匯點, 流量為二分出來的mid, 否則連1, 且mid的最小值為1, 這樣應該好理解吧, 我們二分就是要二分最小的那個值, 然後跑最大流看看每次是不是滿流, 這樣建圖之後我們就可以看到每次二分出來的最小值對這個網路有沒有影響, 因為這樣建圖我們最後得出來的最大流是所有士兵的總和, 滿流了, 那麼就可行, 繼續向上二分,反之向下。
**:這裡用的ek, 較慢, 因為忘了帶dinic了。。。。
#include #include #include #include #include #include using namespace std;
#define inf 0x3f3f3f3f
const int maxed = 300 + 10;
struct e
;struct ek
void add_(int from, int to, int cap)
);edg.push_back((e));
m = edg.size();
g[from].push_back(m - 2);
g[to].push_back(m - 1);
}int maxflow(int s, int t)
}if (a[t])
break;
}if (!a[t])
break;
for (int u = t; u != s; u = edg[p[u]].from)
flow += a[t];
}return flow;
}};char s[maxed][maxed];
int n, p[maxed];
int main()
for (int i = 1; i <= n; ++i)
scanf("%s", s[i] + 1);
int answer = 1;
while (max_ >= min_)
else
max_ = mid - 1;
}printf("%d\n", answer);
}return 0;
}bool slove(int mid)
if (flag)
else
}return ek.maxflow(0, 2 * n + 1) == sum ? true : false;
}
UVA 12264 Risk (二分,網路流)
題意比較坑,移動完以後的士兵不能再次移動,不然樣例都過不了。最小值最大滿足決策單調性所以二分答案,跑網路流驗證是否可行。這種題重點在建圖,為了保證只移動一次,拆點,乙個入點乙個出點,到了出點的自然不能再次排程。不在邊界上的邊連一條容量為1的邊表示至少留乙個人,在邊界上的與t的連邊就設定成mid。其他...
uva 714 貪心 二分
include using namespace std const int maxm 500 int k,m,p maxm bool solve int ans else pre p i return kr k void print int ans else pre p i for int i 0 ...
UVA 11478 差分約束 二分)
題意 給定乙個有向圖,每條邊都有乙個權值,每次你可以選擇乙個結點和乙個整數的,把所有以v為終點的邊的權值減去d,把所有以v為起點的邊的權值加上d 最後要讓所有邊的權的最小值非負且盡量大 include include include include include includeusing name...