Pagini recente » Cod sursa (job #773380) | Cod sursa (job #1657016) | Cod sursa (job #2102228) | Cod sursa (job #731225) | Cod sursa (job #552636)
Cod sursa(job #552636)
// http://infoarena.ro/problema/critice
// http://infoarena.ro/preoni-2005/runda-3/solutii
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
#define maxNodes 1001
#define maxEdges 10001
#define INFINITY 0x3f3f3f3f
#define from first
#define to second
#define source 1
ifstream in("critice.in");
ofstream out("critice.out");
int destination,edges;
bool visitFromSource[maxNodes];
bool visitFromDestination[maxNodes];
int father[maxNodes];
int capacity[maxNodes][maxNodes];
int currentFlow[maxNodes][maxNodes];
vector<int> graph[maxNodes];
pair<int,int> edge[maxEdges];
int critical[maxEdges]; // muchiile critice
void maxFlow();
bool breadthFirst();
void depthFirst(int node,bool visit[]);
int main() {
in >> destination >> edges;
int from,to,flow;
for(int i=1;i<=edges;i++) {
in >> from >> to >> flow;
edge[i] = make_pair(from,to); // pentru identificarea muchiilor critice
// graf neorientat
capacity[from][to] = flow;
capacity[to][from] = flow;
graph[from].push_back(to);
graph[to].push_back(from);
}
maxFlow(); // algoritmul normal de flux
// potentialele muchii critice sunt cele saturate.
// mai precis, sunt muchiile saturate care au propietatea
// ca de la sursa retelei este drum in graful rezidual
// (adica graful care ne ramane daca eliminam muchiile saturate)
// la unul din capetele ei si respectiv de la destinatie la celalalt capat.
// marcam nodurile din graful rezidual
// accesibile din nodul sursa
depthFirst(source,visitFromSource);
// marcam nodurile din graful rezidual
// accesibile din nodul destinatie
depthFirst(destination,visitFromDestination);
// parcurgem toate muchiile
for(int i=1;i<=edges;i++)
// daca este indeplinita conditia de muchie critica
if( (visitFromSource[edge[i].from] && visitFromDestination[edge[i].to]) || (visitFromSource[edge[i].to] && visitFromDestination[edge[i].from]) )
critical[++critical[0]] = i; // retinem indicele muchiei
out << critical[0] << "\n";
for(int i=1;i<=critical[0];i++)
out << critical[i] << "\n";
in.close();
out.close();
return (0);
}
void maxFlow() {
int maxFlow = 0;
vector<int>::iterator it,end;
while(breadthFirst()) {
end = graph[destination].end();
for(it=graph[destination].begin();it!=end;++it)
if(visitFromSource[*it] && capacity[*it][destination] != currentFlow[*it][destination]) {
int minFlow = INFINITY;
father[destination] = *it;
for(int node=destination;node!=source;node=father[node])
minFlow = min(minFlow,capacity[father[node]][node] - currentFlow[father[node]][node]);
if(minFlow) {
for(int node=destination;node!=source;node=father[node]) {
currentFlow[father[node]][node] += minFlow;
currentFlow[node][father[node]] -= minFlow;
}
maxFlow += minFlow;
}
}
}
memset(visitFromSource,0,sizeof(visitFromSource));
}
bool breadthFirst() {
memset(visitFromSource,false,sizeof(visitFromSource));
visitFromSource[source] = true;
int node;
vector<int>::iterator it,end;
queue<int> myQueue;
myQueue.push(source);
while(!myQueue.empty()) {
node = myQueue.front();
myQueue.pop();
if(node == destination)
continue;
end = graph[node].end();
for(it=graph[node].begin();it!=end;++it)
if(!visitFromSource[*it] && currentFlow[node][*it] < capacity[node][*it]) {
visitFromSource[*it] = true;
myQueue.push(*it);
father[*it] = node;
}
}
return visitFromSource[destination];
}
void depthFirst(int node,bool visit[]) {
visit[node] = true;
vector<int>::iterator it,end;
end = graph[node].end();
for(it=graph[node].begin();it!=end;++it)
// daca nodul nu a fost vizitat si muchia formata de tata cu acesta nu este saturata
if(!visit[*it] && capacity[node][*it] > currentFlow[node][*it] && capacity[*it][node] > currentFlow[*it][node])
depthFirst(*it,visit);
}