您的位置:首页 > 其它

poj 3343 二分图匹配+二分枚举

2014-04-06 14:55 471 查看
这个图论也是个1Y(100多行1Y好开心 。◕‿◕。) 题目链接点这里

有关匈牙利算法求二分匹配的内容点这里

由于题目比较臭长。。。所以只把description搬过来了。。。

Against Mammoths

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 1644 Accepted: 534
Description

Back to year 3024, humans finally developed a new technology that enables them to conquer the alien races. The new technology made it possible to produce huge spaceships known as Saber Tooth spaceships as powerful as the aliens' defending mammoths. At that
time, humans ruled several planets while some others were under control of the aliens. Using Saber Tooth ships, humans finally defeated aliens and this became the first Planet War in history. Our goal is to run a simulation of the ancient war to verify some
historical hypotheses.

Producing each spaceship takes an amount of time which is constant for each planet but may vary among different planets. We call the number of spaceships each planet can produce in a year, the production rate of that planet. Note that each planet
has a number of spaceships in it initially (before the simulation starts). The planets start producing ships when the simulation starts, so if a planet has n ships initially, and has the production rate p, it will have n + p ships
at the beginning of year 1, and n + i × p ships at the beginning of year i (years are started from zero).

Bradley Bennett, the commander in chief of the human armies, decided a strategy for the war. For each alien planet A, he chooses a corresponding human planet P, and produces spaceships in P until a certain moment at which he sends all spaceships in P to
invade the planet A. No alien planet is invaded by two human planets and no human planet sends its spaceships to two different alien planets.

The defense power of the alien planets comes from their powerful mammoths. Each alien planet contains a number of mammoths initially and produces a number of mammoths each year (called the production rate of the planet). When a fight between spaceships and
mammoths takes place, the side having the greater number of troops is the winner. If the spaceships win, the alien planet is defeated. In case the number of mammoths and spaceships are equal, the spaceships win.

The difficulty with planning this strategy is that it takes some time for the spaceships to reach the alien planets, and during this time, the aliens produce mammoths. The time required for spaceships to travel from each human planet to each alien planet
is known. The ships can leave their planets only at the beginning of years (right after the ships are produced) and reach the alien planets at the beginning of years too (right after the mammoths are produced).

As an example, consider a human planet with two initial spaceships and production rate three invading an alien planet with two initial mammoths and production rate two. The time required to travel between the two planets is two years and the ships are ordered
to leave at year one. In this case, five ships leave the human planet. When they reach the alien planet, they confront eight mammoths and will be defeated during the fight.

Bennett decided to prepare a plan that destroys every alien planet in the shortest possible time. Your task is to write a program to generate such a plan. The output is the shortest possible time (in years) in which every alien planet is defeated.

题目的意思是说有一堆人类星球以及一堆外星人星球,每个星球上都有其初始拥有的战舰和一个战舰年产值(单位为艘/每年)。而且一个人类星球只能消灭一个外星人星球。问有没有可能消灭所有的外星人星球,如果可能的话,问最少需要多少年可以消灭它们。

很明显建图的话,人类星球是一类点,外星人星球是一类点,而边的话,则是计算人类星球i能否消灭外星人星球j,如果可以消灭,则给两者建一个边。如果可以完成任务的话,最大匹配数应该等于外星人星球的数目,所以这题肯定是求一个最大匹配。

接下来的问题就是如何求出最小的时间,这里用的方法是二分枚举答案(所以建边的时候还要给每条边一个权值,来表示i攻克j时的年份),没次权值大于midium的边不会考虑进去。这样便可以将答案求出来了。

下面放出代码,感觉可以优化的地方还是很多的,不过再优化的话,貌似只能加高编程复杂度

//winoros	544K	563MS	C++	3146B	2014-04-06 14:53:05
//winoros	1092K	688MS	G++	3146B	2014-04-06 14:52:52
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)>(b)?(b):(a))
#define rep(i,initial_n,end_n) for(int (i)=(initial_n);(i)<(end_n);i++)
#define repp(i,initial_n,end_n) for(int (i)=(initial_n);(i)<=(end_n);(i)++)
#define reep(i,initial_n,end_n) for((i)=(initial_n);(i)<(end_n);i++)
#define reepp(i,initial_n,end_n) for((i)=(initial_n);(i)<=(end_n);(i)++)
#define eps 1.0e-9
#define MAX_N 1010

using namespace std;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef long long ll;
typedef unsigned long long ull;

vector<pii> v[260];
bool marked[260], can;
int pre[260], n, m, b, e, ans, tmp, tmpp, ini[2][260], rate[2][260], anss;
pii tmppp;

bool find(int x);
int hungry(int n);

int main() {
while(scanf("%d%d", &n, &m) && (n || m)) {
b = 1 << 30, e = -1, anss = -1;
rep(i, 0, n) scanf("%d%d", &ini[0][i], &rate[0][i]);
rep(i, 0, m) scanf("%d%d", &ini[1][i], &rate[1][i]);
rep(j, 0, n) {
rep(i, 0, m) {
can = false, tmppp.first = i;
scanf("%d", &tmp);
tmpp = (ini[1][i] + tmp * rate[1][i]);
if(ini[0][j] >= tmpp) {
tmppp.second = tmp, v[j].push_back(tmppp), can = true, b = min(b, tmppp.second), e = max(e, tmppp.second);
}
else if(rate[1][i] != rate[0][j] && rate[0][j] - rate[1][i] > 0) {
tmppp.second = (tmpp - ini[0][j]) / (rate[0][j] - rate[1][i]) + ((tmpp - ini[0][j]) % (rate[0][j] - rate[1][i]) == 0 ? 0 : 1) + tmp;
v[j].push_back(tmppp), can = true;
b = min(b, tmppp.second), e = max(e, tmppp.second);
}
}
}
while(b <= e) {
ans = (b + e) / 2;
if(hungry(n) == m) e = ans - 1, anss= ans;
else b = ans + 1;
}
if(anss == -1) puts("IMPOSSIBLE");
else printf("%d\n", anss);
rep(i, 0, n) v[i].clear();
}
return 0;
}

int hungry(int n) {
int sum = 0;
memset(pre, 255, sizeof(pre));
rep(i, 0, n) {
memset(marked, 0, sizeof(marked));
if(find(i)) sum++;
}
return sum;
}

bool find(int x) {
int len = v[x].size();
rep(i, 0, len) {
if(!marked[v[x][i].first] && v[x][i].second <= ans) {
marked[v[x][i].first] = true;
if(pre[v[x][i].first] == -1 || find(pre[v[x][i].first])) {
pre[v[x][i].first] = x;
return true;
}
}
}
return false;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息