相比起443来略为简单。D1三道题分别是简单题、简单题和简单题。
D1 250p Underprimes
没什么好说的,分解质因数,拼手速的题目。
D1 500p BedroomFloor
模拟题,有些麻烦。
首先算出中间完整的正方形个数。然后用边上完整的正方形去和原长方形做交集运算,分出各种小矩形。
最后用4和1相拼,3和2相拼,3和1相拼,2和1相拼,1和1相拼。
return ret;
}
}
D1 1000p NowhereLand
网络流。这个题的建图还不甚清楚,好像是把所有已有的点和源点相连无穷大,可以建立公司的点和汇点相连无穷大,边与边相连1。
已有点设为黑点,不能建立公司的点设为白点,剩下的点黑白染色,求黑白集合间的最小割。
while ( !Q.empty () && dist[d] == 0 )
{
int cur = Q.front (); Q.pop ();
printf ( "%d/n", cur );
for ( int i = 0; i < v; i ++ )
{
if ( a[cur][i] == 0 )
continue;
if ( dist[i] != 0 )
continue;
dist[i] = MIN ( dist[cur], a[cur][i] );
prev[i] = cur;
Q.push ( i );
}
}
printf ( "/n%d/n", dist[d] );
return dist[d];
}
public:
int placeGuards(vector <string> cities, int k, vector <string> guards, vector <string> agencies)
{
int i, j, n = cities.size ();
memset ( guard, 0, sizeof ( guard ) );
memset ( agency, 0, sizeof ( agency ) );
for ( i = 0; i < guards.size (); i ++ )
{
istringstream in ( guards[i] );
int x;
while ( in >> x )
guard[i][x] = 1;
}
for ( i = 0; i < agencies.size (); i ++ )
{
istringstream in ( agencies[i] );
int x;
while ( in >> x )
agency[i][x] = 1;
}
src = n, dst = n + 1;
int flow = 0;
int iter;
for ( iter = 0; iter < n; iter ++ )
{
memset ( a, 0, sizeof ( a ) );
for ( i = 0; i < n; i ++ )
for ( j = 0; j < n; j ++ )
if ( cities[i][j] == '1' )
a[i][j] = 1;
for ( i = 0; i < n; i ++ )
if ( !agency[i][iter] )
a[i][dst] = 10000;
for ( i = 0; i < n; i ++ )
if ( guard[i][iter] )
a[src][i] = 10000;
memset ( prev, 0xff, sizeof ( prev ) );
for ( int f; f = fflow ( src, dst, n + 2 ) > 0; )
{
flow += f;
for ( int b = dst; b != src; b = prev[b] )
{
a[prev[b]][b] -= f;
a[b][prev[b]] += f;
}
}
}
return flow;
}
}
改进版最大流模板,适用于稀疏矩阵:
void clear ( int _N )
{
N = _N, len = 0;
for ( int i = 0; i < N; i ++ )
e[i].clear ();
}
void addEdge ( int i, int j, int c1, int c2 )
{
//printf ( "%d %d %d %d/n", i, j, c1, c2 );
e[i].push_back ( MP ( j, len ) );
flow[len ++] = c1;
e[j].push_back ( MP ( i, len ) );
flow[len ++] = c2;
}
int bfs ()
{
for ( int i = 0; i < N; i ++ )
dist[i] = 0;
dist[src] = INF; Q.push ( src );
while ( !Q.empty () )
{
int cur = Q.front ();
Q.pop ();
for ( int i = 0; i < e[cur].size (); i ++ )
{
int v = e[cur][i].first, j = e[cur][i].second;
if ( dist[v] || flow[j] == 0 )
continue;
dist[v] = min ( dist[cur], flow[j] );
prev[v] = cur, edge[v] = j;
Q.push ( v );
}
}
return dist[dst];
}
int maxFlow ()
{
int ret = 0;
for ( int f; ( f = bfs () ) > 0; )
{
ret += f;
for ( int v = dst; v != src; v = prev[v] )
{
flow[edge[v]] -= f;
int j = ( edge[v] & 1 ) ? edge[v] - 1 : edge[v] + 1;
flow[j] += f;
}
}
return ret;
}
}