hdu4975 行列和构造矩阵(dp判断唯一性)
2024-10-21 18:36:59
题意:
和hdu4888一样,只不过是数据加强了,就是给你行列的和,让你构造一个矩阵,然后判断矩阵是否唯一。
思路:
构造矩阵很简单,跑一次最大流就行了,关键是判断矩阵的唯一性,之前的那个4888我用的是深搜找环过的,这个题目就TLE了,数据加强了,对于判断矩阵的唯一性我们可以这么想假如某一行的i列和j列满足 i列的这个> 0 && j列的这个 < 9此时我们再在另一行找到 i列的这个< 9 && j列的这个 > 0就可以把>0 的拿出来一个放在<9的上面,这样答案就不唯一了,对于最大流跑完后的到的矩阵,如果我们暴力判断上面的哪些情况的话是大约O(n^4)这样就比DFS找环还浪费时间,所以我们要用到dp优化,dp[i][j]记录的是在当前的状态之前,是否存在在某一行中,i列<9,j列>0,这样我们就可以利用之前状态的结果来节省一层for(具体看代码),但是这样还是TLE了,我们在每个for前面加几个小优化就可以过了。
#include<stdio.h>
#include<string.h>
#include<queue> #define N_node 1005
#define N_edge 600000
#define INF 1000000000
using namespace std; typedef struct
{
int to ,next ,cost;
}STAR; typedef struct
{
int t ,x;
}DEP; STAR E[N_edge];
DEP xin ,tou;
int list[N_node] ,listt[N_node] ,tot;
int deep[N_node];
int row[505] ,col[505];
int map[505][505];
int dp[505][505]; void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot; E[++tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
} bool BFS_Deep(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
deep[s] = 0;
xin.x = s ,xin.t = 0;
queue<DEP>q;
q.push(xin);
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.t = tou.t + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.t;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
listt[i] = list[i];
return deep[t] != -1;
} int minn(int x ,int y)
{
return x < y ? x : y;
} int DFS_Flow(int s ,int t ,int flow)
{
if(s == t) return flow;
int nowflow = 0;
for(int k = listt[s] ;k ;k = E[k].next)
{
listt[s] = k;
int to = E[k].to;
int c = E[k].cost;
if(deep[to] != deep[s] + 1 || !c)
continue;
int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
nowflow += tmp;
E[k].cost -= tmp;
E[k^1].cost += tmp;
if(flow == nowflow)break;
}
if(!nowflow) deep[s] = 0;
return nowflow;
} int DINIC(int s ,int t ,int n)
{
int ans = 0;
while(BFS_Deep(s ,t ,n))
{
ans += DFS_Flow(s ,t ,INF);
}
return ans;
} bool jude(int n ,int m ,int mktot)
{ int i = 1 ,j = 1 ,k;
for(k = mktot + 1 ;k <= tot ;k += 2)
{
map[i][j] = E[k].cost;
if(++j > m) {i ++ ,j = 1;}
}
memset(dp ,0 ,sizeof(dp));
for(i = 1 ;i <= n ;i ++)
{
if(row[i] == 0 || m * 9 == row[i])continue;
for(j = 1 ;j <= m ;j ++)
{
if(col[j] == 0 || n * 9 == col[j])continue;
for(k = j + 1 ;k <= m ;k ++)
{
int mk1 = 0 ,mk2 = 0;
if(map[i][j] < 9 && map[i][k] > 0)
{
if(dp[k][j]) return 1;
mk1 ++;
}
if(map[i][j] > 0 && map[i][k] < 9)
{
if(dp[j][k]) return 1;
mk2 ++;
}
if(mk1) dp[j][k] = 1;
if(mk2) dp[k][j] = 1;
}
}
}
return 0;
} int main ()
{
int n ,m ,i ,j ,s1 ,s2 ,a ,mkk;
int t ,cas = 1;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&n ,&m);
s1 = s2 = mkk = 0;
memset(list ,0 ,sizeof(list)) ,tot = 1;
for(i = 1 ;i <= n ;i ++)
{
scanf("%d" ,&a);
add(0 ,i ,a);
s1 += a;
if(m * 9 < a) mkk = 1;
row[i] = a;
}
for(i = 1 ;i <= m ;i ++)
{
scanf("%d" ,&a);
add(i + n ,n + m + 1 ,a);
s2 += a;
col[i] = a;
if(n * 9 < a) mkk = 1;
}
printf("Case #%d: " ,cas ++);
if(s1 != s2 || mkk)
{
puts("So naive!");
continue;
}
int mktot = tot + 1;
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= m ;j ++)
add(i ,j + n ,9);
int maxflow = DINIC(0 ,n + m + 1 ,n + m + 1);
if(s1 != maxflow)
{
puts("So naive!");
continue;
}
jude(n ,m ,mktot)? puts("So young!"):puts("So simple!");
}
return 0;
}
最新文章
- 关于repaint(重绘)和reflow( 回流)
- father of the archangel of death";?
- [No000057]一个人默默背单词,小心被传染哦
- sitemesh使用步骤
- 调用WEKA包进行kmeans聚类(java)
- Support Library官方教程(3)android studio中导入支援包
- RequireJs 深入理解
- 【Java基础】foreach循环
- MVC5+EF6 入门完整教程 总目录
- [ACM] POJ 3252 Round Numbers (的范围内的二元0数大于或等于1数的数目,组合)
- Mysql的排他锁和共享锁
- 最简单的基于DirectShow的示例:视频播放器
- 机器学习---最小二乘线性回归模型的5个基本假设(Machine Learning Least Squares Linear Regression Assumptions)
- poj1456 Supermarket 贪心+并查集
- SSL 3.0曝出Poodle漏洞的解决方案
- SSH免密登录实现
- Kaldi中的Chain模型
- Robot Framework 三种测试用例模式
- Linux 搜索日志信息
- 并查集(Union-Find) 应用举例 --- 基础篇
热门文章
- 剑指 Offer 32 - III. 从上到下打印二叉树 III + 双端队列使用 + 蛇形打印层次遍历序列 + 正倒序输出
- 剑指 Offer 04. 二维数组中的查找 (思维)
- POJ-2253(最短路变形+dijikstra算法+求解所有路径中所有最长边中的一个最小值)
- 10个顶级Python实用库,推荐你试试!
- super_curd组件技术点总结
- 2019HDU多校第七场 HDU6646 A + B = C 【模拟】
- C#无边框窗体拖动代码
- Ubuntu之软件包管理 (最全最精)
- C语言之动态内存管理
- 高精度加法(c++)