Problem J: Installing Diagnostic Software

You have recently been appointed as the administrator for a wired network of devices. Unfortunately, your predecessor used very poor quality lines to connect the devices. The board of executives is currently deciding if they want to fund an upgrade to a wireless network, or simply replace the existing wires with ones of better quality. As expected, this decision is being weighed down with bureaucratic nonsense; it looks like it will take some time before anything is approved.
Meanwhile, you still have to deal with the problem at hand. You have access to an antiquated version of Newton Network Monitor which is a software package that, once installed on a machine, will monitor all lines connected to that machine and immediately alert the user when a line has failed. This should help reduce your response time to any failures.
Your task is to install the software on some machines so each line is being monitored by at least one of its endpoint devices. For various technical reasons, the time it takes to install the software varies from device to device so you want to minimize the total amount of time spent installing the software. You cannot install on more than one machine at a time (since you only have one copy of the software) meaning the total time spent installing the software is exactly the sum of the installation times on each machine.
Input Format
Each input case begins with two numbers n,m with 1 ≤ n ≤ 1,000 and 0 ≤ m ≤ 25,000. Following this are m pairs of distinct integers between 0 and n-1 which describe a wire connecting the two devices. The time spent installing the software on machine numbered i is 2i. The input is terminated with n = m = 0; this should not be processed.
Output Format
For each input case, there is to be one line of output containing a sequence of n bits with no spaces. The i'th bit is 1 if the software is installed on machine i, and 0 if not.
Sample Input
3 2 0 2 1 2 3 1 1 2 0 0
Sample Output
110 010
Zachary Friggstad
题目大意是给你n个点m条边,要你在每条边上的两个点至少有一个点装上一个软件,每个点的编号是0~n-1,花费是 2i
让你安排一种方案使花费最小
贪心的策略为从编号大的开始遍历 如果它的儿子不是树枝,那么就不取它,直接取它的儿子(根据二进制的大小关系)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1000+10;
struct line{
int from,to;
line(int from ,int to):from(from),to(to){}
friend bool operator <(line a,line b){
if(a.from != b.from) return a.from > b.from;
else return a.to < b.to;
}
};
vector<line> vl;
vector<int> g[maxn];
int n,m;
bool vis[maxn];
int main(){
while(cin >> n >> m && n+m){
vl.clear();
memset(vis,0,sizeof vis);
while(m--){
int a,b;
cin >> a >> b;
if(a < b) swap(a,b);
vl.push_back(line(a,b));
}
sort(vl.begin(),vl.end());
for(int i = 0; i < n; i++) g[i].clear();
for(int i = 0; i < vl.size(); ){
int t = vl[i].from,j=i;
while(vl[j].from == t&&j<vl.size()){
g[t].push_back(vl[j].to);
g[vl[j].to].push_back(t);
j++;
}
i = j;
}
for(int i = n-1; i >= 0; i--){
bool flag = 0;
if(vis[i]) continue;
for(int k = 0; k < g[i].size(); k++){
if(g[g[i][k]].size()==0){
flag = 1;
break;
}
}
if(flag) vis[i] = 1;
else{
for(int k = 0; k < g[i].size(); k++)
vis[g[i][k]] = 1;
}
}
for(int i = 0; i < n; i++)
cout<<vis[i];
cout<<endl;
}
return 0;
}